aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@google.com>2023-08-29 22:31:30 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2023-08-29 22:31:30 +0000
commitee132a3ba2a7295008913e19af9328d0954f240e (patch)
treef40c1a21c47e1a74164c5feb8a577145a2970aeb
parentf9490653f18ce1f2997b79d6ef6d46f2b10ee44d (diff)
parentf1db2cd21ffd0089578fd72dd32e3df5f2f40f44 (diff)
downloadpyfakefs-ee132a3ba2a7295008913e19af9328d0954f240e.tar.gz
Upgrade pyfakefs to 979a878b12a3f625abe986a2249b677e6193ae3d am: a3bcabf4b7 am: 78fdc2ac9e am: 1261801ef1 am: 9f1f3798d8 am: f1db2cd21fHEADmastermain
Original change: https://android-review.googlesource.com/c/platform/external/python/pyfakefs/+/2726660 Change-Id: I5d286395144c422ac19f4b0c0a1b5279f14942b7 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md14
-rw-r--r--.github/ISSUE_TEMPLATE/feature_request.md2
-rw-r--r--.github/PULL_REQUEST_TEMPLATE.md14
-rw-r--r--.github/workflows/builddocs.yml53
-rw-r--r--.github/workflows/dockerfiles/Dockerfile_debian19
-rw-r--r--.github/workflows/dockerfiles/Dockerfile_fedora10
-rw-r--r--.github/workflows/dockerfiles/Dockerfile_redhat (renamed from .github/workflows/dockerfiles/Dockerfile_centos)22
-rw-r--r--.github/workflows/dockerfiles/Dockerfile_ubuntu19
-rw-r--r--.github/workflows/dockertests.yml6
-rw-r--r--.github/workflows/release-deploy.yml34
-rwxr-xr-x.github/workflows/run_pytest.sh8
-rw-r--r--.github/workflows/testsuite.yml (renamed from .github/workflows/pythonpackage.yml)90
-rw-r--r--.pre-commit-config.yaml51
-rw-r--r--.readthedocs.yaml13
-rw-r--r--CHANGES.md345
-rw-r--r--CONTRIBUTING.md40
-rw-r--r--Dockerfile10
-rw-r--r--METADATA21
-rw-r--r--README.md112
-rw-r--r--docs/api.rst40
-rw-r--r--docs/autopatch.rst29
-rw-r--r--docs/conf.py102
-rw-r--r--docs/index.rst3
-rw-r--r--docs/intro.rst45
-rw-r--r--docs/modules.rst16
-rw-r--r--docs/pyfakefs_theme/static/pyfakefs.css1
-rw-r--r--docs/troubleshooting.rst245
-rw-r--r--docs/usage.rst473
-rw-r--r--extra_requirements.txt10
-rwxr-xr-xpyfakefs/__init__.py2
-rw-r--r--pyfakefs/_version.py2
-rw-r--r--pyfakefs/deprecator.py69
-rw-r--r--pyfakefs/extra_packages.py2
-rw-r--r--pyfakefs/fake_file.py1316
-rw-r--r--pyfakefs/fake_filesystem.py4588
-rwxr-xr-xpyfakefs/fake_filesystem_shutil.py51
-rw-r--r--pyfakefs/fake_filesystem_unittest.py698
-rw-r--r--pyfakefs/fake_io.py188
-rw-r--r--pyfakefs/fake_open.py361
-rw-r--r--pyfakefs/fake_os.py1374
-rw-r--r--pyfakefs/fake_path.py529
-rw-r--r--pyfakefs/fake_pathlib.py1044
-rw-r--r--pyfakefs/fake_scandir.py46
-rw-r--r--pyfakefs/helpers.py226
-rw-r--r--pyfakefs/mox3_stubout.py28
-rw-r--r--pyfakefs/patched_packages.py67
-rw-r--r--pyfakefs/py.typed1
-rw-r--r--pyfakefs/pytest_plugin.py59
-rw-r--r--pyfakefs/pytest_tests/conftest.py4
-rw-r--r--pyfakefs/pytest_tests/example.py2
-rw-r--r--pyfakefs/pytest_tests/io.py14
-rw-r--r--pyfakefs/pytest_tests/ns_package/test/ns_package/test/test_file.py7
-rw-r--r--pyfakefs/pytest_tests/ns_package/test/setup.py0
-rw-r--r--pyfakefs/pytest_tests/pytest_check_failed_plugin_test.py13
-rw-r--r--pyfakefs/pytest_tests/pytest_doctest_test.py22
-rw-r--r--pyfakefs/pytest_tests/pytest_fixture_param_test.py12
-rw-r--r--pyfakefs/pytest_tests/pytest_fixture_test.py12
-rw-r--r--pyfakefs/pytest_tests/pytest_module_fixture_test.py26
-rw-r--r--pyfakefs/pytest_tests/pytest_plugin_failing_helper.py2
-rw-r--r--pyfakefs/pytest_tests/pytest_plugin_test.py42
-rw-r--r--pyfakefs/pytest_tests/segfault_test.py16
-rw-r--r--pyfakefs/tests/all_tests.py38
-rw-r--r--pyfakefs/tests/all_tests_without_extra_packages.py2
-rw-r--r--pyfakefs/tests/dynamic_patch_test.py30
-rw-r--r--pyfakefs/tests/example.py9
-rw-r--r--pyfakefs/tests/example_test.py107
-rw-r--r--pyfakefs/tests/fake_filesystem_glob_test.py60
-rw-r--r--pyfakefs/tests/fake_filesystem_shutil_test.py257
-rw-r--r--pyfakefs/tests/fake_filesystem_test.py2239
-rw-r--r--pyfakefs/tests/fake_filesystem_unittest_test.py608
-rw-r--r--pyfakefs/tests/fake_filesystem_vs_real_test.py507
-rw-r--r--pyfakefs/tests/fake_open_test.py1608
-rw-r--r--pyfakefs/tests/fake_os_test.py3653
-rw-r--r--pyfakefs/tests/fake_pathlib_test.py1154
-rw-r--r--pyfakefs/tests/fake_stat_time_test.py45
-rw-r--r--pyfakefs/tests/fake_tempfile_test.py53
-rw-r--r--pyfakefs/tests/fixtures/config_module.py2
-rw-r--r--pyfakefs/tests/fixtures/deprecated_property.py7
-rw-r--r--pyfakefs/tests/fixtures/module_with_attributes.py10
-rw-r--r--pyfakefs/tests/import_as_example.py19
-rw-r--r--pyfakefs/tests/logsio.py2
-rw-r--r--pyfakefs/tests/mox3_stubout_test.py110
-rw-r--r--pyfakefs/tests/patched_packages_test.py33
-rw-r--r--pyfakefs/tests/performance_test.py18
-rw-r--r--pyfakefs/tests/test_utils.py183
-rw-r--r--pyproject.toml3
-rw-r--r--requirements.txt2
-rw-r--r--requirements_dev.txt1
-rw-r--r--setup.cfg64
-rw-r--r--setup.py93
-rw-r--r--tox.ini4
91 files changed, 13136 insertions, 10455 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 84ac229..37d93ca 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -8,17 +8,19 @@ assignees: ''
---
**Describe the bug**
-A clear and concise description of what the bug is.
-Please provide a stack trace if available.
+Describe the observed behavior, and what you expect to happen instead.
+In case of a crash, please provide the complete stack trace.
**How To Reproduce**
-Please provide a unit test or a minimal code snippet that reproduces the
-problem.
+Please provide a unit test or a minimal reproducible example that shows
+the problem.
**Your environment**
-Please run the following and paste the output.
+Please run the following in the environment where the problem happened and
+paste the output.
```bash
python -c "import platform; print(platform.platform())"
python -c "import sys; print('Python', sys.version)"
-python -c "from pyfakefs.fake_filesystem import __version__; print('pyfakefs', __version__)"
+python -c "from pyfakefs import __version__; print('pyfakefs', __version__)"
+python -c "import pytest; print('pytest', pytest.__version__)"
```
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 75dac2d..e12f065 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -2,7 +2,7 @@
name: Feature request
about: Suggest an idea for this project
title: ''
-labels: ''
+labels: 'enhancement'
assignees: ''
---
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..76469e1
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,14 @@
+<!--
+Please prefix your PR title with [WIP] for PRs that are still in progress.
+-->
+
+#### Describe the changes
+The related issue or a description of the bug or feature that this PR addresses.
+
+#### Tasks
+- [ ] Unit tests added that reproduce the issue or prove feature is working
+- [ ] Fix or feature added
+- [ ] Entry to release notes added
+- [ ] Pre-commit CI shows no errors
+- [ ] Unit tests passing
+- [ ] For documentation changes: The Read the Docs preview builds and looks as expected
diff --git a/.github/workflows/builddocs.yml b/.github/workflows/builddocs.yml
deleted file mode 100644
index 9092b1a..0000000
--- a/.github/workflows/builddocs.yml
+++ /dev/null
@@ -1,53 +0,0 @@
-name: DocBuild
-
-on:
- push:
- branches: master
-
-defaults:
- run:
- shell: bash
-
-jobs:
- build_docs:
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ubuntu-latest]
- python-version: [3.8]
- steps:
- - name: Checkout master
- uses: actions/checkout@v2
- with:
- path: main
- - name: Get last commit message
- run: |
- cd main
- echo "LAST_COMMIT=$(echo `git log -1 --pretty=%B`)" >> $GITHUB_ENV
- cd ..
- - name: Install needed packages
- run: |
- pip3 install wheel
- pip3 install pytest
- sudo apt update
- sudo apt-get install python3-sphinx
- cd main/docs
- make html
- - name: Checkout gh-pages
- uses: actions/checkout@v2
- with:
- ref: gh-pages
- path: doc
- - name: Copy and commit changes
- run: |
- cp -r main/gh-pages/* doc/master
- cd doc
- git config user.name "CI Build"
- git config user.email "pyfakefs@gmail.com"
- git add master/*
- if [ `git status -s | wc -l` = 0 ]; then
- echo "No changes in built documentation, skipping"
- exit 0
- fi
- git commit -a -m "$LAST_COMMIT"
- git push
diff --git a/.github/workflows/dockerfiles/Dockerfile_debian b/.github/workflows/dockerfiles/Dockerfile_debian
index 0012e77..7d34f4f 100644
--- a/.github/workflows/dockerfiles/Dockerfile_debian
+++ b/.github/workflows/dockerfiles/Dockerfile_debian
@@ -20,27 +20,30 @@ RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
-ARG github_repo=jmcgeheeiv/pyfakefs
-ARG github_branch=master
+ARG github_repo=pytest-dev/pyfakefs
+ARG github_branch=main
RUN apt-get update && apt-get install -y \
python3-pip \
unzip \
- wget
+ wget \
+ python3-venv
+
RUN apt-get clean
RUN useradd -u 1000 pyfakefs
RUN mkdir -p work \
- && wget https://github.com/$github_repo/archive/$github_branch.zip \
- && unzip $github_branch.zip -d work
+ && wget https://github.com/$github_repo/archive/$github_branch.zip -O archive.zip \
+ && unzip archive.zip -d work
RUN WORK_DIR=`ls -d work/*`; mv $WORK_DIR work/pyfakefs
RUN chown -R pyfakefs:pyfakefs work/pyfakefs
WORKDIR work/pyfakefs
-RUN pip3 install -r requirements.txt
-RUN pip3 install -r extra_requirements.txt
+RUN python3 -m venv ../venv
+RUN ../venv/bin/pip install -r requirements.txt
+RUN ../venv/bin/pip install -r extra_requirements.txt
USER pyfakefs
ENV PYTHONPATH work/pyfakefs
ENV TEST_REAL_FS=1
-CMD ["python3", "-m", "pyfakefs.tests.all_tests"]
+CMD ["../venv/bin/python", "-m", "pyfakefs.tests.all_tests"]
diff --git a/.github/workflows/dockerfiles/Dockerfile_fedora b/.github/workflows/dockerfiles/Dockerfile_fedora
index 5cb9dee..9b6b5bd 100644
--- a/.github/workflows/dockerfiles/Dockerfile_fedora
+++ b/.github/workflows/dockerfiles/Dockerfile_fedora
@@ -12,22 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-FROM fedora:32
+FROM fedora:latest
MAINTAINER jmcgeheeiv@users.noreply.github.com
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
-ARG github_repo=jmcgeheeiv/pyfakefs
-ARG github_branch=master
+ARG github_repo=pytest-dev/pyfakefs
+ARG github_branch=main
RUN dnf install -y python3-pip unzip wget
RUN useradd -u 1000 pyfakefs
RUN mkdir -p work \
- && wget https://github.com/$github_repo/archive/$github_branch.zip \
- && unzip $github_branch.zip -d work
+ && wget https://github.com/$github_repo/archive/$github_branch.zip -O archive.zip \
+ && unzip archive.zip -d work
RUN WORK_DIR=`ls -d work/*`; mv $WORK_DIR work/pyfakefs
RUN chown -R pyfakefs:pyfakefs work/pyfakefs
WORKDIR work/pyfakefs
diff --git a/.github/workflows/dockerfiles/Dockerfile_centos b/.github/workflows/dockerfiles/Dockerfile_redhat
index f22fb63..00bb825 100644
--- a/.github/workflows/dockerfiles/Dockerfile_centos
+++ b/.github/workflows/dockerfiles/Dockerfile_redhat
@@ -12,23 +12,25 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-FROM centos:7
-MAINTAINER jmcgeheeiv@users.noreply.github.com
+FROM registry.access.redhat.com/ubi9/ubi
+LABEL maintainer="John McGehee"
-ENV LANG en_US.UTF-8
-ENV LANGUAGE en_US:en
-ENV LC_ALL en_US.UTF-8
-
-ARG github_repo=jmcgeheeiv/pyfakefs
-ARG github_branch=master
+ARG github_repo=pytest-dev/pyfakefs
+ARG github_branch=main
+RUN yum update --disablerepo=* --enablerepo=ubi-9-appstream-rpms --enablerepo=ubi-9-baseos-rpms -y
RUN yum install -y python3-pip unzip wget
+RUN python3 --version
+
+ENV LANG en_US.UTF-8
+ENV LANGUAGE en_US:en
+ENV LC_COLLATE C.UTF-8
RUN useradd -u 1000 pyfakefs
RUN mkdir -p work \
- && wget https://github.com/$github_repo/archive/$github_branch.zip \
- && unzip $github_branch.zip -d work
+ && wget https://github.com/$github_repo/archive/$github_branch.zip -O archive.zip \
+ && unzip archive.zip -d work
RUN WORK_DIR=`ls -d work/*`; mv $WORK_DIR work/pyfakefs
RUN chown -R pyfakefs:pyfakefs work/pyfakefs
WORKDIR work/pyfakefs
diff --git a/.github/workflows/dockerfiles/Dockerfile_ubuntu b/.github/workflows/dockerfiles/Dockerfile_ubuntu
index 2e235cd..f76fa31 100644
--- a/.github/workflows/dockerfiles/Dockerfile_ubuntu
+++ b/.github/workflows/dockerfiles/Dockerfile_ubuntu
@@ -20,27 +20,30 @@ RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
-ARG github_repo=jmcgeheeiv/pyfakefs
-ARG github_branch=master
+ARG github_repo=pytest-dev/pyfakefs
+ARG github_branch=main
RUN apt-get update && apt-get install -y \
python3-pip \
unzip \
- wget
+ wget \
+ python3-venv
+
RUN apt-get clean
RUN useradd -u 1000 pyfakefs
RUN mkdir -p work \
- && wget https://github.com/$github_repo/archive/$github_branch.zip \
- && unzip $github_branch.zip -d work
+ && wget https://github.com/$github_repo/archive/$github_branch.zip -O archive.zip \
+ && unzip archive.zip -d work
RUN WORK_DIR=`ls -d work/*`; mv $WORK_DIR work/pyfakefs
RUN chown -R pyfakefs:pyfakefs work/pyfakefs
WORKDIR work/pyfakefs
-RUN pip3 install -r requirements.txt
-RUN pip3 install -r extra_requirements.txt
+RUN python3 -m venv ../venv
+RUN ../venv/bin/pip install -r requirements.txt
+RUN ../venv/bin/pip install -r extra_requirements.txt
USER pyfakefs
ENV PYTHONPATH work/pyfakefs
ENV TEST_REAL_FS=1
-CMD ["python3", "-m", "pyfakefs.tests.all_tests"]
+CMD ["../venv/bin/python", "-m", "pyfakefs.tests.all_tests"]
diff --git a/.github/workflows/dockertests.yml b/.github/workflows/dockertests.yml
index af77346..9daa2ad 100644
--- a/.github/workflows/dockertests.yml
+++ b/.github/workflows/dockertests.yml
@@ -9,11 +9,11 @@ jobs:
strategy:
fail-fast: false
matrix:
- docker-image: [centos, debian, fedora, ubuntu]
+ docker-image: [debian, fedora, ubuntu, redhat]
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Setup docker container
run: |
- docker build -t pyfakefs -f $GITHUB_WORKSPACE/.github/workflows/dockerfiles/Dockerfile_${{ matrix.docker-image }} . --build-arg github_repo=$GITHUB_REPOSITORY --build-arg github_branch=$(basename $GITHUB_REF)
+ docker build -t pyfakefs -f $GITHUB_WORKSPACE/.github/workflows/dockerfiles/Dockerfile_${{ matrix.docker-image }} . --build-arg github_repo=$GITHUB_REPOSITORY --build-arg github_branch=$GITHUB_REF_NAME
- name: Run tests
run: docker run -t pyfakefs
diff --git a/.github/workflows/release-deploy.yml b/.github/workflows/release-deploy.yml
new file mode 100644
index 0000000..41f4369
--- /dev/null
+++ b/.github/workflows/release-deploy.yml
@@ -0,0 +1,34 @@
+name: release-deploy
+
+on:
+ release:
+ types: [ published ]
+
+jobs:
+
+ deploy:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: true
+ matrix:
+ python-version: [ '3.10' ]
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v4
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ - name: Build package
+ run: |
+ python -m pip install --upgrade pip
+ python -m pip install build
+ python -m build
+
+ - name: Publish package to PyPI
+ uses: pypa/gh-action-pypi-publish@release/v1
+ with:
+ user: __token__
+ password: ${{ secrets.PYPI_TOKEN }}
diff --git a/.github/workflows/run_pytest.sh b/.github/workflows/run_pytest.sh
deleted file mode 100755
index 725deb9..0000000
--- a/.github/workflows/run_pytest.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-python -m pytest pyfakefs/pytest_tests/pytest_plugin_test.py
-if [[ $PY_VERSION == '3.6' ]] || [[ $PY_VERSION == '3.7' ]] || [[ $PY_VERSION == '3.8' ]] || [[ $PY_VERSION == '3.9' ]] ; then
- python -m pytest pyfakefs/pytest_tests/pytest_fixture_test.py
-fi
-python -m pytest pyfakefs/pytest_tests/pytest_plugin_failing_helper.py > ./testresult.txt
-python -m pytest pyfakefs/pytest_tests/pytest_check_failed_plugin_test.py
diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/testsuite.yml
index 25f0527..51b59b2 100644
--- a/.github/workflows/pythonpackage.yml
+++ b/.github/workflows/testsuite.yml
@@ -4,43 +4,20 @@ on:
[push, pull_request]
jobs:
- linter:
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ubuntu-latest]
- python-version: [3.8]
+ pytype:
+ runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v2
+ - name: Check out repository
+ uses: actions/checkout@v3
+ - name: Set up Python
+ uses: actions/setup-python@v4
with:
- python-version: ${{ matrix.python-version }}
- - name: Install linter
+ python-version: "3.10"
+ - name: install pytype
+ run: pip install setuptools pytype pytest scandir pathlib2 pandas xlrd django
+ - name: Run pytype
run: |
- uname -a
- python -m pip install flake8 mypy
- - name: Check syntax and style
- run: flake8 . --exclude get-pip.py --max-complexity=13 --statistics
-
- mypy:
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ubuntu-latest]
- python-version: [3.8]
- steps:
- - uses: actions/checkout@v2
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v2
- with:
- python-version: ${{ matrix.python-version }}
- - name: Install dependencies
- run: |
- python -m pip install -r requirements.txt -r extra_requirements.txt
- python -m pip install mypy==0.812
- - name: Run typing checks
- run: python -m mypy .
+ pytype pyfakefs --keep-going --exclude pyfakefs/tests/* --exclude pyfakefs/pytest_tests/*
tests:
runs-on: ${{ matrix.os }}
@@ -48,15 +25,19 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
- python-version: [3.6, 3.7, 3.8, 3.9, "3.10"]
+ python-version: ["3.8", "3.9", "3.10", "3.11", "3.12-dev"]
include:
- - python-version: pypy3
+ - python-version: "pypy-3.7"
+ os: ubuntu-latest
+ - python-version: "pypy-3.9"
+ os: ubuntu-latest
+ - python-version: "pypy-3.10"
os: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
@@ -68,7 +49,7 @@ jobs:
- name: Cache dependencies
id: cache-dep
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: ${{ matrix.os }}-${{ matrix.python-version }}-pip-${{ hashFiles('**/requirements.txt') }}-${{ hashFiles('**/extra_requirements.txt') }}
@@ -77,9 +58,8 @@ jobs:
- name: Install dependencies
run: |
- pip install wheel
+ pip install setuptools wheel
pip install -r requirements.txt
- pip install .
- name: Run unit tests without extra packages as non-root user
run: |
export TEST_REAL_FS=1
@@ -97,10 +77,12 @@ jobs:
fi
shell: bash
- name: Install extra dependencies
+ if: ${{ matrix.python-version != '3.12-dev' }}
run: |
pip install -r extra_requirements.txt
shell: bash
- name: Run unit tests with extra packages as non-root user
+ if: ${{ matrix.python-version != '3.12-dev' }}
run: |
python -m pyfakefs.tests.all_tests
shell: bash
@@ -117,27 +99,33 @@ jobs:
strategy:
fail-fast: false
matrix:
- os: [ubuntu-latest, windows-latest]
- python-version: [3.9]
- pytest-version: [3.0.0, 3.5.1, 4.0.2, 4.5.0, 5.0.1, 5.4.3, 6.0.2, 6.2.5, 7.0.1, 7.1.0]
+ os: [ubuntu-latest, macOS-latest, windows-latest]
+ python-version: ["3.9"]
+ pytest-version: [3.0.0, 3.5.1, 4.0.2, 4.5.0, 5.0.1, 5.4.3, 6.0.2, 6.2.5, 7.0.1, 7.1.3, 7.2.0, 7.3.1, 7.4.0]
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -U pytest==${{ matrix.pytest-version }}
+ pip install opentimelineio
+ pip install -e .
if [[ '${{ matrix.pytest-version }}' == '4.0.2' ]]; then
pip install -U attrs==19.1.0
fi
shell: bash
- name: Run pytest tests
run: |
- export PY_VERSION=${{ matrix.python-version }}
- $GITHUB_WORKSPACE/.github/workflows/run_pytest.sh
+ echo "$(python -m pytest pyfakefs/pytest_tests/pytest_plugin_failing_helper.py)" > ./testresult.txt
+ python -m pytest pyfakefs/pytest_tests
+ if [[ '${{ matrix.pytest-version }}' > '3.0.0' ]]; then
+ cd pyfakefs/pytest_tests/ns_package
+ python -m pytest --log-cli-level=INFO test
+ fi
shell: bash
dependency-check:
@@ -145,11 +133,11 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
- python-version: [3.9]
+ python-version: ["3.10"]
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v2
+ uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..f1bcd07
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,51 @@
+default_language_version:
+ python: "3.10"
+
+repos:
+ - repo: https://github.com/codespell-project/codespell
+ rev: v2.2.5
+ hooks:
+ - id: codespell
+ args:
+ - --ignore-words-list=wronly,afile
+ - repo: https://github.com/psf/black
+ rev: 23.7.0
+ hooks:
+ - id: black
+ args: [ --safe, --quiet ]
+ - repo: https://github.com/asottile/blacken-docs
+ rev: 1.16.0
+ hooks:
+ - id: blacken-docs
+ additional_dependencies: [ black==22.12.0 ]
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.4.0
+ hooks:
+ - id: trailing-whitespace
+ - id: end-of-file-fixer
+ - id: fix-encoding-pragma
+ args: [ --remove ]
+ - id: check-yaml
+ - id: debug-statements
+ language_version: python3
+ - repo: https://github.com/PyCQA/autoflake
+ rev: v2.2.0
+ hooks:
+ - id: autoflake
+ name: autoflake
+ args: ["--in-place", "--remove-unused-variables", "--remove-all-unused-imports"]
+ language: python
+ files: \.py$
+ - repo: https://github.com/PyCQA/flake8
+ rev: 6.1.0
+ hooks:
+ - id: flake8
+ language_version: python3
+ additional_dependencies:
+ - flake8-bugbear
+ args: ["--extend-ignore=E203", "--max-line-length=88"]
+ - repo: https://github.com/pre-commit/mirrors-mypy
+ rev: v1.5.1
+ hooks:
+ - id: mypy
+ exclude: (docs|pyfakefs/tests)
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000..4a0cd14
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,13 @@
+# Read the Docs configuration file for Sphinx projects
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+version: 2
+
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.11"
+
+sphinx:
+ configuration: docs/conf.py
+ fail_on_warning: true
diff --git a/CHANGES.md b/CHANGES.md
index 1d59511..23958e8 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,13 +1,227 @@
# pyfakefs Release Notes
-The released versions correspond to PyPi releases.
+The released versions correspond to PyPI releases.
## Unreleased
+### Changes
+* removed support for Python 3.7 (end of life)
+
+### Fixes
+* removed a leftover debug print statement (see [#869](../../issues/869))
+* make sure tests work without HOME environment set (see [#870](../../issues/870))
+
+## [Version 5.2.3](https://pypi.python.org/pypi/pyfakefs/5.2.3) (2023-08-18)
+Fixes a rare problem on pytest shutdown.
+
+### Fixes
+* Clear the patched module cache on session shutdown (pytest only)
+ (see [#866](../../issues/866)). Added a class method `Patcher.cler_fs_cache`
+ for clearing the patched module cache.
+
+## [Version 5.2.3](https://pypi.python.org/pypi/pyfakefs/5.2.3) (2023-07-10)
+Adds compatibility with PyPy 3.10 and Python 3.12.
+
+### Fixes
+* Re-create temp directory if it had been created before on resetting file system
+ (see [#814](../../issues/814)).
+* Exclude pytest `pathlib` modules from patching to avoid mixup of patched/unpatched
+ code (see [#814](../../issues/814)).
+* Adapt to changes in Python 3.12 beta1 (only working partially,
+ see [#830](../../issues/830) and [#831](../../issues/831)).
+* Adapt to changes in `shutil` in Python 3.12 beta2 (see [#814](../../issues/814)).
+* Fix support for newer PyPi versions (see [#859](../../issues/859)).
+
+### Documentation
+* Added a note regarding the incompatibility of the built-in `sqlite3` module with
+ `pyfakefs` (see [#850](../../issues/850))
+
+### Infrastructure
+* Added pytype check for non-test modules in CI (see [#599](../../issues/599)).
+* Added tests for different pypy3 versions.
+* Added codespell hook to pre-commit
+
+## [Version 5.2.2](https://pypi.python.org/pypi/pyfakefs/5.2.2) (2023-04-13)
+Fixes a regression in 5.2.0
+
+### Changes
+* Made the user and group IDs accessible via dedicated ``get_uid`` and ``get_gid``
+ functions (for symmetry to ``set_uid`` / ``set_gid``)
+
+### Fixes
+* The test fixture is now included in the source distribution and installed
+ with the package.
+* Some public constants in `fake_filesystem` that had been moved to `helpers` are
+ made accessible from there again (see [#809](../../issues/809)).
+* Add missing fake implementations for `os.getuid` and `os.getgid` (Posix only)
+* Make sure a `/tmp` path exists under linux (`TMPDIR` may point elsewhere)
+ (see [#810](../../issues/810))
+
+
+## [Version 5.2.1](https://pypi.python.org/pypi/pyfakefs/5.2.1) (2023-04-11)
+Support for latest Python 3.12 version.
+
+### Changes
+* Adapted fake pathlib to changes in Python 3.12a7 (last alpha version)
+
+### Fixes
+* Properties defining the capabilities of some `os` functions like
+ `os.supports_follow_symlinks` are now properly faked to contain the fake functions
+ if the real functions are faked (see [#799](../../issues/799))
+
+## [Version 5.2.0](https://pypi.python.org/pypi/pyfakefs/5.2.0) (2023-03-31)
+Supports current Python 3.12 version (alpha 6). We plan to make patch releases in
+case of breaking changes in alpha or beta versions.
+
+### Changes
+* Fake module classes previously defined in `fake_filesystem` have now moved to
+ their own modules: `fake_os.FakeOsModule`, `fake_path.FakePathModule`,
+ `fake_io.FakeIoModule` and `fake_open.FakeFileOpen`. Additionally, all fake file
+ classes have been moved to `fake_file`. While most of the changes shall be upwards
+ compatible, we cannot exclude that we missed some problems.
+* Under macOS, at test start a symlink `/tmp` to the actual temporary directory is
+ now created in the fake filesystem.
+* Patching of parsers for pandas >= 1.2 is removed since pandas now uses Python fs functions
+ internally even when the engine selected is "c".
+
+### Features
+* added possibility to set a path inaccessible under Windows by using `chown()` with
+ the `force_unix_mode` flag (see [#720](../../issues/720))
+* added support for current Python 3.12 version (alpha 6)
+* added support for `os.path.splitroot` (new in Python 3.12)
+
+## [Version 5.1.0](https://pypi.python.org/pypi/pyfakefs/5.1.0) (2023-01-12)
+New version before Debian freeze
+
+### Features
+* added class level setup method `setUpClassPyfakefs` for unittest and class-scoped
+ fixture `fs_class` for pytest (see [#752](../../issues/752))
+* added experimental support for Python 3.12: added fake APIs for Windows junction
+ support. These are not implemented and always return `False`.
+
+### Infrastructure
+* replaced end-of-life CentOS with RedHat UBI9 docker image
+* added tests for pytest 7.2.0
+* added black to pre-commit checks, which caused some changes to the
+ coding style (max line length is now 88, always use double quotes)
+* added Python 3.12 to the test suite.
+* migrated to [setuptools declarative syntax](https://setuptools.pypa.io/en/latest/userguide/declarative_config.html).
+* fixed docker tests when running on branches containing forward slashes
+
+## [Version 5.0.0](https://pypi.python.org/pypi/pyfakefs/5.0.0) (2022-10-09)
+New version after the transfer to `pytest-dev`.
+
+### Changes
+* the old-style API deprecated since version 3.4 has now been removed
+* the method `copyRealFile` deprecated since version 3.2 has been removed -
+ use `add_real_file` instead
+
+### Infrastructure
+* transferred the repository to the `pytest-dev` organization
+* renamed the `master` branch to `main`
+* added automatic PyPI release workflow
+* move documentation from GitHub Pages to Read the Docs
+
+### New Features
+* added some support for `st_blocks` in stat result
+ (see [#722](../../issues/722))
+
+### Fixes
+* fixed handling of `O_TMPFILE` in `os.open` (caused handling of
+ `O_DIRECTORY` as `O_TMPFILE`) (see [#723](../../issues/723))
+* fixed handling of read permissions (see [#719](../../issues/719))
+
+## [Version 4.7.0](https://pypi.python.org/pypi/pyfakefs/4.7.0) (2022-09-18)
+Changed handling of nested fixtures and bug fixes.
+
+### Changes
+* `fs` fixtures cannot be nested; any nested `fs` fixture (for example
+ inside an `fs_session` or `fs_module` fixture) will just reference the outer
+ fixture (the behavior had been unexpected before)
+
+### Fixes
+* reverted a performance optimization introduced in version 3.3.0 that
+ caused hanging tests with installed torch (see [#693](../../issues/693))
+* do not use the built-in opener in `pathlib` as it may cause problems
+ (see [#697](../../issues/697))
+* add support for path-like objects in `shutil.disk_usage`
+ (see [#699](../../issues/699))
+* do not advertise support for Python 3.6 in `setup.py`
+ (see [#707](../../issues/707))
+* return the expected type from `fcntl.ioctl` and `fcntl.fcntl` calls if `arg`
+ is of type `byte`; the call itself does nothing as before
+* do not skip filesystem modules by name to allow using own modules with
+ the same name (see [#707](../../issues/707))
+* add missing support for `os.renames` (see [#714](../../issues/714))
+
+## [Version 4.6.3](https://pypi.python.org/pypi/pyfakefs/4.6.3) (2022-07-20)
+Another patch release that fixes a regression in version 4.6.
+
+### Changes
+* automatically reset filesystem on changing `is_windows_fs` or `is_macos`
+ (see [#692](../../issues/692)) - ensures better upwards compatibility in
+ most cases
+
+ :warning: Make sure you write to the filesystem _after_ you change
+ `is_windows_fs` or `is_macos`, otherwise the changes will be lost.
+
+### Fixes
+* fixed regression: `os.path.exists` returned `True` for any root drive path under Windows
+
+## [Version 4.6.2](https://pypi.python.org/pypi/pyfakefs/4.6.2) (2022-07-14)
+Patch release that fixes an error in the previous patch.
+
+### Fixes
+* fixed support for `opener` introduced in previous patch release
+ (see [#689](../../issues/689))
+
+## [Version 4.6.1](https://pypi.python.org/pypi/pyfakefs/4.6.1) (2022-07-13)
+Fixes incompatibility with Python 3.11 beta 4.
+
+_Note_: Python 3.11 is only supported in the current beta 4 version, problems
+with later beta or rc versions are still possible. We will try to fix such
+problems in short order should they appear.
+
+### Fixes
+* added support for `opener` argument in `open`, which is used in `tempfile`
+ in Python 3.11 since beta 4 (see [#686](../../issues/686))
+
+### Infrastructure
+* make sure tests run without `pyfakefs` installed as a package
+ (see [#687](../../issues/687))
+
+## [Version 4.6.0](https://pypi.python.org/pypi/pyfakefs/4.6.0) (2022-07-12)
+Adds support for Python 3.11, removes support for Python 3.6, changes root
+path behavior under Windows.
+
+### Changes
+* Python 3.6 has reached its end of life on 2021/12/23 and is no
+ longer officially supported by pyfakefs
+ * `os.stat_float_times` has been removed in Python 3.7 and is therefore no
+ longer supported
+* under Windows, the root path is now effectively `C:\` instead of `\`; a
+ path starting with `\` points to the current drive as in the real file
+ system (see [#673](../../issues/673))
+* fake `pathlib.Path.owner()` and `pathlib.Path.group()` now behave like the
+ real methods - they look up the real user/group name for the user/group id
+ that is associated with the fake file (see [#678](../../issues/678))
+
+### New Features
+* added some support for the upcoming Python version 3.11
+ (see [#677](../../issues/677))
+* added convenience fixtures for module- and session based `fs` fixtures
+ (`fs_module` and `fs_session`)
+
+### Fixes
+* fixed an incompatibility of `tmpdir` (and probably other fixtures) with the
+ module-scoped version of `fs`; had been introduced in
+ pyfakefs 4.5.5 by the fix for [#666](../../issues/666)
+ (see [#684](../../issues/684))
+
## [Version 4.5.6](https://pypi.python.org/pypi/pyfakefs/4.5.6) (2022-03-17)
Fixes a regression which broke tests with older pytest versions (< 3.9).
### Changes
-* minimum supported pytest version is now 3.0 (older versions do not work
+* minimum supported pytest version is now 3.0 (older versions do not work
properly with current Python versions)
### Fixes
@@ -42,20 +256,20 @@ Reverts a change in the previous release that could cause a regression.
### Changes
* `os.listdir`, `os.scandir` and `pathlib.Path.listdir` now return the
- directory list in a random order only if explicitly configured in the
- file system (use `fs.shuffle_listdir_results = True` with `fs` being the
- file system). In a future version, the default may be changed to better
+ directory list in a random order only if explicitly configured in the
+ file system (use `fs.shuffle_listdir_results = True` with `fs` being the
+ file system). In a future version, the default may be changed to better
reflect the real filesystem behavior (see [#647](../../issues/647))
-
+
## [Version 4.5.2](https://pypi.python.org/pypi/pyfakefs/4.5.2) (2021-11-07)
This is a bugfix release.
### Changes
* `os.listdir`, `os.scandir` and `pathlib.Path.listdir` now return the
directory list in a random order (see [#638](../../issues/638))
-* the `fcntl` module under Unix is now mocked, e.g. all functions have no
+* the `fcntl` module under Unix is now mocked, e.g. all functions have no
effect (this may be changed in the future if needed,
- see [#645](../../issues/645))
+ see [#645](../../issues/645))
### Fixes
* fixed handling of alternative path separator in `os.path.split`,
@@ -64,7 +278,7 @@ This is a bugfix release.
* fixed handling of failed rename due to permission error
(see [#643](../../issues/643))
-
+
## [Version 4.5.1](https://pypi.python.org/pypi/pyfakefs/4.5.1) (2021-08-29)
This is a bugfix release.
@@ -75,9 +289,9 @@ This is a bugfix release.
(see [#614](../../issues/614))
* do not import pandas and related modules if it is not patched
(see [#627](../../issues/627))
-* handle `pathlib.Path.owner()` and `pathlib.Path.group` by returning
+* handle `pathlib.Path.owner()` and `pathlib.Path.group` by returning
the current user/group name (see [#629](../../issues/629))
-* fixed handling of `use_known_patches=False` (could cause an exception)
+* fixed handling of `use_known_patches=False` (could cause an exception)
* removed Python 3.5 from metadata to disable installation for that version
(see [#615](../../issues/615))
@@ -89,31 +303,31 @@ This is a bugfix release.
## [Version 4.5.0](https://pypi.python.org/pypi/pyfakefs/4.5.0) (2021-06-04)
Adds some support for Python 3.10 and basic type checking.
-_Note_: This version has been yanked from PyPi as it erroneously allowed
+_Note_: This version has been yanked from PyPI as it erroneously allowed
installation under Python 3.5.
### New Features
* added support for some Python 3.10 features:
- * new method `pathlib.Path.hardlink_to`
+ * new method `pathlib.Path.hardlink_to`
* new `newline` argument in `pathlib.Path.write_text`
* new `follow_symlinks` argument in `pathlib.Path.stat` and
`pathlib.Path.chmod`
- * new 'strict' argument in `os.path.realpath`
+ * new 'strict' argument in `os.path.realpath`
### Changes
- * Python 3.5 has reached its end of life in September 2020 and is no longer
+ * Python 3.5 has reached its end of life in September 2020 and is no longer
supported
* `pathlib2` is still supported, but considered to have the same
functionality as `pathlib` and is no longer tested separately;
the previous behavior broke newer `pathlib` features if `pathlib2`
was installed (see [#592](../../issues/592))
-
+
### Fixes
* correctly handle byte paths in `os.path.exists`
(see [#595](../../issues/595))
* Update `fake_pathlib` to support changes coming in Python 3.10
([see](https://github.com/python/cpython/pull/19342)
- * correctly handle UNC paths in `os.path.split` and in directory path
+ * correctly handle UNC paths in `os.path.split` and in directory path
evaluation (see [#606](../../issues/606))
### Infrastructure
@@ -121,17 +335,17 @@ installation under Python 3.5.
## [Version 4.4.0](https://pypi.python.org/pypi/pyfakefs/4.4.0) (2021-02-24)
Adds better support for Python 3.8 / 3.9.
-
+
### New Features
- * added support for `pathlib.Path.link_to` (new in Python 3.8)
+ * added support for `pathlib.Path.link_to` (new in Python 3.8)
(see [#580](../../issues/580))
- * added support for `pathlib.Path.readlink` (new in Python 3.9)
+ * added support for `pathlib.Path.readlink` (new in Python 3.9)
(see [#584](../../issues/584))
* added `FakeFilesystem.create_link` convenience method which creates
intermittent directories (see [#580](../../issues/580))
-
+
### Fixes
- * fixed handling of pipe descriptors in the fake filesystem
+ * fixed handling of pipe descriptors in the fake filesystem
(see [#581](../../issues/581))
* added non-functional argument `effective_ids` to `os.access`
(see [#585](../../issues/585))
@@ -163,10 +377,10 @@ This is a bugfix release that fixes a regression introduced in version 4.2.0.
## [Version 4.3.1](https://pypi.python.org/pypi/pyfakefs/4.3.1) (2020-11-23)
This is an update to the performance release, with more setup caching and the
-possibility to disable it.
+possibility to disable it.
### Changes
-* Added caching of patched modules to avoid lookup overhead
+* Added caching of patched modules to avoid lookup overhead
* Added `use_cache` option and `clear_cache` method to be able
to deal with unwanted side effects of the newly introduced caching
@@ -187,39 +401,39 @@ release.
keyword arguments `fs`. This avoids confusion with the pytest `fs`
fixture and conforms to the behavior of `mock.patch`. You may have to
adapt the argument order if you use the `patchfs` and `mock.patch`
- decorators together (see [#566](../../issues/566))
+ decorators together (see [#566](../../issues/566))
* Default arguments that are file system functions are now _not_ patched by
default to avoid a large performance impact. An additional parameter
`patch_default_args` has been added that switches this behavior on
(see [#567](../../issues/567)).
* Added performance improvements in the test setup, including caching the
the unpatched modules
-
+
## [Version 4.2.1](https://pypi.python.org/pypi/pyfakefs/4.2.1) (2020-11-02)
This is a bugfix release that fixes a regression issue.
### Fixes
- * remove dependency of pyfakefs on `pytest` (regression,
- see [#565](../../issues/565))
+ * remove dependency of pyfakefs on `pytest` (regression,
+ see [#565](../../issues/565))
## [Version 4.2.0](https://pydpi.python.org/pypi/pyfakefs/4.2.0) (2020-11-01)
#### New Features
- * add support for the `buffering` parameter in `open`
+ * add support for the `buffering` parameter in `open`
(see [#549](../../issues/549))
- * add possibility to patch `io.open_code` using the new argument
+ * add possibility to patch `io.open_code` using the new argument
`patch_open_code` (since Python 3.8)
(see [#554](../../issues/554))
- * add possibility to set file system OS via `FakeFilesystem.os`
-
+ * add possibility to set file system OS via `FakeFilesystem.os`
+
#### Fixes
* fix check for link in `os.walk` (see [#559](../../issues/559))
* fix handling of real files in combination with `home` if simulating
Posix under Windows (see [#558](../../issues/558))
- * do not call fake `open` if called from skipped module
+ * do not call fake `open` if called from skipped module
(see [#552](../../issues/552))
- * do not call fake `pathlib.Path` if called from skipped module
+ * do not call fake `pathlib.Path` if called from skipped module
(see [#553](../../issues/553))
* fixed handling of `additional_skip_names` with several module components
* allow to open existing pipe file descriptor
@@ -240,12 +454,12 @@ This is a bugfix release that fixes a regression issue.
#### New Features
* Added some support for pandas (`read_csv`, `read_excel` and more), and
- for django file locks to work with the fake filesystem
+ for django file locks to work with the fake filesystem
(see [#531](../../issues/531))
-
+
#### Fixes
* `os.expanduser` now works with a bytes path
- * Do not override global warnings setting in `Deprecator`
+ * Do not override global warnings setting in `Deprecator`
(see [#526](../../issues/526))
* Make sure filesystem modules in `pathlib` are patched
(see [#527](../../issues/527))
@@ -257,9 +471,9 @@ This is a bugfix release that fixes a regression issue.
## [Version 4.0.2](https://pypi.python.org/pypi/pyfakefs/4.0.2) (2020-03-04)
-This as a patch release that only builds for Python 3. Note that
-versions 4.0.0 and 4.0.1 will be removed from PyPi to disable
-installing them under Python 2.
+This as a patch release that only builds for Python 3. Note that
+versions 4.0.0 and 4.0.1 will be removed from PyPI to disable
+installing them under Python 2.
#### Fixes
* Do not build for Python 2 (see [#524](../../issues/524))
@@ -268,7 +482,7 @@ installing them under Python 2.
This as a bug fix release for a regression bug.
-_Note_: This version has been yanked from PyPi as it erroneously allowed
+_Note_: This version has been yanked from PyPI as it erroneously allowed
installation under Python 2. This has been fixed in version 4.0.2.
#### Fixes
@@ -278,12 +492,12 @@ installation under Python 2. This has been fixed in version 4.0.2.
pyfakefs 4.0.0 drops support for Python 2.7. If you still need
Python 2.7, you can continue to use pyfakefs 3.7.x.
-_Note_: This version has been yanked from PyPi as it erroneously allowed
+_Note_: This version has been yanked from PyPI as it erroneously allowed
installation under Python 2. This has been fixed in version 4.0.2.
#### Changes
* Removed Python 2.7 and 3.4 support (see [#492](../../issues/492))
-
+
#### New Features
* Added support for handling keyword-only arguments in some `os` functions
* Added possibility to pass additional parameters to `fs` pytest fixture
@@ -291,12 +505,12 @@ installation under Python 2. This has been fixed in version 4.0.2.
functions
* Added convenience decorator `patchfs` to patch single functions using
the fake filesystem
-
+
#### Fixes
* Added missing `st_ino` in `makedir` (see [#515](../../issues/515))
* Fixed handling of relative paths in `lresolve` / `os.lstat`
(see [#516](../../issues/516))
- * Fixed handling of byte string paths
+ * Fixed handling of byte string paths
(see [#517](../../issues/517))
* Fixed `os.walk` if path ends with path separator
(see [#512](../../issues/512))
@@ -304,14 +518,14 @@ installation under Python 2. This has been fixed in version 4.0.2.
(see [#510](../../issues/510))
* Fixed handling of `os.TMPFILE` flag under Linux
(see [#509](../../issues/509) and [#511](../../issues/511))
- * Adapted fake `pathlib` to changes in Python 3.7.6/3.8.1
+ * Adapted fake `pathlib` to changes in Python 3.7.6/3.8.1
(see [#508](../../issues/508))
- * Fixed behavior of `os.makedirs` in write-protected directory
+ * Fixed behavior of `os.makedirs` in write-protected directory
(see [#507](../../issues/507))
## [Version 3.7.2](https://pypi.python.org/pypi/pyfakefs/3.7.2) (2020-03-02)
-This version backports some fixes from master.
+This version backports some fixes from main.
#### Fixes
* Fixed handling of relative paths in `lresolve` / `os.lstat`
@@ -322,7 +536,7 @@ This version backports some fixes from master.
(see [#510](../../issues/510))
* Fixed handling of `os.TMPFILE` flag under Linux
(see [#509](../../issues/509) and [#511](../../issues/511))
- * Fixed behavior of `os.makedirs` in write-protected directory
+ * Fixed behavior of `os.makedirs` in write-protected directory
(see [#507](../../issues/507))
## [Version 3.7.1](https://pypi.python.org/pypi/pyfakefs/3.7.1) (2020-02-14)
@@ -330,14 +544,14 @@ This version backports some fixes from master.
This version adds support for Python 3.7.6 and 3.8.1.
#### Fixes
- * Adapted fake `pathlib` to changes in Python 3.7.6/3.8.1
- (see [#508](../../issues/508)) (backported from master)
-
+ * Adapted fake `pathlib` to changes in Python 3.7.6/3.8.1
+ (see [#508](../../issues/508)) (backported from main)
+
## [Version 3.7](https://pypi.python.org/pypi/pyfakefs/3.7) (2019-11-23)
This version adds support for Python 3.8.
-_Note:_ This is the last pyfakefs version that will support Python 2.7
+_Note:_ This is the last pyfakefs version that will support Python 2.7
and Python 3.4 (possible bug fix releases notwithstanding).
#### New Features
@@ -349,16 +563,16 @@ and Python 3.4 (possible bug fix releases notwithstanding).
#### Fixes
* support `devnull` in Windows under Python 3.8
- (see [#504](../../issues/504))
- * fixed side effect of calling `DirEntry.stat()` under Windows (changed
+ (see [#504](../../issues/504))
+ * fixed side effect of calling `DirEntry.stat()` under Windows (changed
st_nlink) (see [#502](../../issues/502))
- * fixed problem of fake modules still referenced after a test in modules
+ * fixed problem of fake modules still referenced after a test in modules
loaded during the test (see [#501](../../issues/501) and [#427](../../issues/427))
* correctly handle missing read permission for parent directory
(see [#496](../../issues/496))
* raise for `os.scandir` with non-existing directory
(see [#498](../../issues/498))
-
+
#### Infrastructure
* fixed CI tests scripts to always propagate errors
(see [#500](../../issues/500))
@@ -368,9 +582,9 @@ and Python 3.4 (possible bug fix releases notwithstanding).
#### Fixes
* avoid rare side effect during module iteration in test setup
(see [#338](../../issues/338))
- * make sure real OS tests are not executed by default
+ * make sure real OS tests are not executed by default
(see [#495](../../issues/495))
-
+
## [Version 3.6](https://pypi.python.org/pypi/pyfakefs/3.6) (2019-06-30)
#### Changes
@@ -386,7 +600,7 @@ and Python 3.4 (possible bug fix releases notwithstanding).
* added basic support for `os.pipe` (see [#473](../../issues/473))
* added support for symlinks in `add_real_directory`
* added new public method `add_real_symlink`
-
+
#### Infrastructure
* added check for correctly installed Python 3 version in Travis.CI
(see [#487](../../issues/487))
@@ -402,11 +616,11 @@ and Python 3.4 (possible bug fix releases notwithstanding).
## [Version 3.5.8](https://pypi.python.org/pypi/pyfakefs/3.5.8) (2019-06-21)
-Another bug-fix release that mainly fixes a regression wih Python 2 that has
+Another bug-fix release that mainly fixes a regression with Python 2 that has
been introduced in version 3.5.3.
#### Fixes
- * regression: patching build-in `open` under Python 2 broke unit tests
+ * regression: patching built-in `open` under Python 2 broke unit tests
(see [#469](../../issues/469))
* fixed writing to file added with `add_real_file`
(see [#470](../../issues/470))
@@ -495,6 +709,7 @@ This is mostly a bug-fix release.
To switch them off for legacy code, use:
```python
from pyfakefs.deprecator import Deprecator
+
Deprecator.show_warnings = False
```
@@ -693,7 +908,7 @@ This is the last release that supports Python 2.6.
File contents are read from the real file system only as needed ([#170](../../issues/170)).
See `example_test.py` for a usage example.
* Deprecated `TestCase.copyRealFile()` in favor of `add_real_file()`.
- `copyRealFile()` remains only for backward compatability. Also, some
+ `copyRealFile()` remains only for backward compatibility. Also, some
less-popular argument combinations have been disallowed.
* Added this file you are reading, `CHANGES.md`, to the release manifest
@@ -738,7 +953,7 @@ This is the last release that supports Python 2.6.
* Support for `glob.iglob` ([#59](../../issues/59))
#### Infrastructure
- * Added [auto-generated documentation](http://jmcgeheeiv.github.io/pyfakefs/)
+ * Added [auto-generated documentation](http://pytest-dev.github.io/pyfakefs/)
#### Fixes
* `shutil.move` incorrectly moves directories ([#145](../../issues/145))
@@ -802,5 +1017,5 @@ This is the last release that supports Python 2.6.
* Relative paths not supported ([#16](../../issues/16), [#17](../../issues/17)))
## Older Versions
-There are no release notes for releases 2.6 and below. The following versions are still available on PyPi:
+There are no release notes for releases 2.6 and below. The following versions are still available on PyPI:
* [1.1](https://pypi.python.org/pypi/pyfakefs/1.1), [1.2](https://pypi.python.org/pypi/pyfakefs/1.2), [2.0](https://pypi.python.org/pypi/pyfakefs/2.0), [2.1](https://pypi.python.org/pypi/pyfakefs/2.1), [2.2](https://pypi.python.org/pypi/pyfakefs/2.2), [2.3](https://pypi.python.org/pypi/pyfakefs/2.3) and [2.4](https://pypi.python.org/pypi/pyfakefs/2.4)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 9d2daf5..6fa4b52 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,7 +2,7 @@
# Contributing to pyfakefs
We welcome any contributions that help to improve pyfakefs for the community.
-Contributions may include bug reports, bug fixes, new features, infrastructure enhancements, or
+Contributions may include bug reports, bug fixes, new features, infrastructure enhancements, or
documentation updates.
## How to contribute
@@ -10,7 +10,7 @@ documentation updates.
### Reporting Bugs
If you think you found a bug in pyfakefs, you can [create an issue](https://help.github.com/articles/creating-an-issue/).
-Before filing the bug, please check, if it still exists in the [master branch](https://github.com/jmcgeheeiv/pyfakefs).
+Before filing the bug, please check, if it still exists in the [main branch](https://github.com/pytest-dev/pyfakefs).
If you can reproduce the problem, please provide enough information so that it can be reproduced by other developers.
This includes:
* The Operating System
@@ -21,36 +21,38 @@ For better readability, you may use [markdown code formatting](https://help.gith
### Proposing Enhancements
-If you need a specific feature that is not implemented, or have an idea for the next
-exciting gimmick in pyfakefs, you can also create a respective issue.
-Of course - implementing it yourself is the best chance to get it done!
+If you need a specific feature that is not implemented, or have an idea for the next
+exciting gimmick in pyfakefs, you can also create a respective issue.
+Of course - implementing it yourself is the best chance to get it done!
The next item has some information on doing this.
### Contributing Code
-The preferred workflow for contributing code is to
-[fork](https://help.github.com/articles/fork-a-repo/) the [repository](https://github.com/jmcgeheeiv/pyfakefs) on GitHub, clone it,
+The preferred workflow for contributing code is to
+[fork](https://help.github.com/articles/fork-a-repo/) the [repository](https://github.com/pytest-dev/pyfakefs) on GitHub, clone it,
develop on a feature branch, and [create a pull request](https://help.github.com/articles/creating-a-pull-request-from-a-fork) when done.
There are a few things to consider for contributing code:
- * Please use the standard [PEP-8 coding style](https://www.python.org/dev/peps/pep-0008/)
- (your IDE or tools like [pep8](https://pypi.python.org/pypi/pep8) or [pylint](https://pypi.python.org/pypi/pylint) will help you)
+ * We ensure the [PEP-8 coding style](https://www.python.org/dev/peps/pep-0008/)
+ by using [black](https://pypi.org/project/black/) auto-format in a
+ pre-commit hook; you can locally install
+ [pre-commit](https://pypi.org/project/pre-commit/) to run the linter
+ tests on check-in or on demand (`pre-commit run --all-files`)
* Use the [Google documentation style](https://google.github.io/styleguide/pyguide.html) to document new public classes or methods
* Provide unit tests for bug fixes or new functionality - check the existing tests for examples
* Provide meaningful commit messages - it is ok to amend the commits to improve the comments
- * Check that the automatic tests on [Travis](https://travis-ci.org/jmcgeheeiv/pyfakefs)
- and [AppVeyor](https://ci.appveyor.com/project/jmcgeheeiv/pyfakefs) all pass for your pull request
- * Be ready to adapt your changes after a code review
-
+ * Check that the automatic GitHub Action CI tests all pass for your pull request
+ * Be ready to adapt your changes after a code review
+
### Contributing Documentation
If you want to improve the existing documentation, you can do this also using a pull request.
You can contribute to:
- * the source code documentation using [Google documentation style](https://google.github.io/styleguide/pyguide.html)
- * the [README](https://github.com/jmcgeheeiv/pyfakefs/blob/master/README.md) using [markdown syntax](https://help.github.com/articles/basic-writing-and-formatting-syntax/)
- * the documentation published on [GitHub Pages](http://jmcgeheeiv.github.io/pyfakefs/),
- located in the `docs` directory (call `make html` from that directory).
- For building the documentation, you will need [sphinx](http://sphinx.pocoo.org/).
- * [this file](https://github.com/jmcgeheeiv/pyfakefs/blob/master/CONTRIBUTING.md)
+ * the source code documentation using [Google documentation style](https://google.github.io/styleguide/pyguide.html)
+ * the [README](https://github.com/pytest-dev/pyfakefs/blob/main/README.md) using [markdown syntax](https://help.github.com/articles/basic-writing-and-formatting-syntax/)
+ * the documentation published on [Read the Docs](https://pytest-pyfakefs.readthedocs.io/en/latest/),
+ located in the `docs` directory (call `make html` from that directory).
+ For building the documentation, you will need [sphinx](http://sphinx.pocoo.org/).
+ * [this file](https://github.com/pytest-dev/pyfakefs/blob/main/CONTRIBUTING.md)
if you want to enhance the contributing guide itself
Thanks for taking the time to contribute to pyfakefs!
diff --git a/Dockerfile b/Dockerfile
index 8018db5..99524b8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -41,13 +41,13 @@ RUN apt-get clean
RUN useradd -u 1000 pyfakefs
-RUN wget https://github.com/jmcgeheeiv/pyfakefs/archive/master.zip \
- && unzip master.zip \
- && chown -R pyfakefs:pyfakefs /pyfakefs-master
-WORKDIR /pyfakefs-master
+RUN wget https://github.com/pytest-dev/pyfakefs/archive/main.zip \
+ && unzip main.zip \
+ && chown -R pyfakefs:pyfakefs /pyfakefs-main
+WORKDIR /pyfakefs-main
RUN pip3 install -r requirements.txt
RUN pip3 install -r extra_requirements.txt
USER pyfakefs
-ENV PYTHONPATH /pyfakefs-master
+ENV PYTHONPATH /pyfakefs-main
CMD ["python3", "-m", "pyfakefs.tests.all_tests"]
diff --git a/METADATA b/METADATA
index f58e4d3..c81cd98 100644
--- a/METADATA
+++ b/METADATA
@@ -1,10 +1,9 @@
-name: "pyfakefs"
-description:
- "pyfakefs implements a fake file system that mocks the Python file system "
- "modules. Using pyfakefs, your tests operate on a fake file system in "
- "memory without touching the real disk. The software under test requires no "
- "modification to work with pyfakefs."
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update python/pyfakefs
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
+name: "pyfakefs"
+description: "pyfakefs implements a fake file system that mocks the Python file system modules. Using pyfakefs, your tests operate on a fake file system in memory without touching the real disk. The software under test requires no modification to work with pyfakefs."
third_party {
url {
type: HOMEPAGE
@@ -12,9 +11,13 @@ third_party {
}
url {
type: GIT
- value: "https://github.com/jmcgeheeiv/pyfakefs.git"
+ value: "https://github.com/pytest-dev/pyfakefs.git"
}
- version: "9a387966d65e20e465ed03af5b3bfb632984adc3"
+ version: "979a878b12a3f625abe986a2249b677e6193ae3d"
license_type: NOTICE
- last_upgrade_date { year: 2022 month: 03 day: 30 }
+ last_upgrade_date {
+ year: 2023
+ month: 8
+ day: 25
+ }
}
diff --git a/README.md b/README.md
index 559cb12..cbdf11f 100644
--- a/README.md
+++ b/README.md
@@ -1,84 +1,97 @@
-# pyfakefs [![PyPI version](https://badge.fury.io/py/pyfakefs.svg)](https://badge.fury.io/py/pyfakefs) [![Python version](https://img.shields.io/pypi/pyversions/pyfakefs.svg)](https://img.shields.io/pypi/pyversions/pyfakefs.svg) ![Testsuite](https://github.com/jmcgeheeiv/pyfakefs/workflows/Testsuite/badge.svg)
+# pyfakefs [![PyPI version](https://badge.fury.io/py/pyfakefs.svg)](https://badge.fury.io/py/pyfakefs) [![Python version](https://img.shields.io/pypi/pyversions/pyfakefs.svg)](https://img.shields.io/pypi/pyversions/pyfakefs.svg) ![Testsuite](https://github.com/pytest-dev/pyfakefs/workflows/Testsuite/badge.svg) [![Documentation Status](https://readthedocs.org/projects/pytest-pyfakefs/badge/?version=latest)](https://pytest-pyfakefs.readthedocs.io/en/latest/?badge=latest) [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/pytest-dev/pyfakefs/main.svg)](https://results.pre-commit.ci/latest/github/pytest-dev/pyfakefs/main)
+
pyfakefs implements a fake file system that mocks the Python file system modules.
Using pyfakefs, your tests operate on a fake file system in memory without
-touching the real disk. The software under test requires no modification to
+touching the real disk. The software under test requires no modification to
work with pyfakefs.
-pyfakefs works with Linux, Windows and MacOS.
+Pyfakefs creates a new empty in-memory file system at each test start, which replaces
+the real filesystem during the test. Think of pyfakefs as making a per-test temporary
+directory, except for an entire file system.
+
+There are several means to achieve this: by using
+the `fs` fixture if running pytest, by using `fake_filesystem_unittest.TestCase` as a
+base class if using unittest, by using a `fake_filesystem_unittest.Patcher` instance
+as a context manager, or by using the `patchfs` decorator.
+
+
+
+pyfakefs works with current versions of Linux, Windows and macOS.
## Documentation
-This file provides general usage instructions for pyfakefs. There is more:
-
-* The documentation at [GitHub Pages:](http://jmcgeheeiv.github.io/pyfakefs)
- * The [Release documentation](http://jmcgeheeiv.github.io/pyfakefs/release)
- contains usage documentation for pyfakefs and a description of the
- most relevant classes, methods and functions for the last version
- released on PyPi
- * The [Development documentation](http://jmcgeheeiv.github.io/pyfakefs/master)
- contains the same documentation for the current master branch
- * The [Release 3.7 documentation](http://jmcgeheeiv.github.io/pyfakefs/release37)
- contains usage documentation for the last version of pyfakefs
+This document provides a general overview for pyfakefs. There is more:
+
+* The documentation at **Read the Docs**:
+ * The [Release documentation](https://pytest-pyfakefs.readthedocs.io/en/stable)
+ contains usage documentation for pyfakefs and a description of the
+ most relevant classes, methods and functions for the last version
+ released on PyPI
+ * The [Development documentation](https://pytest-pyfakefs.readthedocs.io/en/latest)
+ contains the same documentation for the current main branch
+ * The [Release 3.7 documentation](https://pytest-pyfakefs.readthedocs.io/en/v3.7.2/)
+ contains usage documentation for the last version of pyfakefs
supporting Python 2.7
- * The [Release 3.3 documentation](http://jmcgeheeiv.github.io/pyfakefs/release33)
- contains usage documentation for the last version of pyfakefs
- supporting Python 2.6, and for the old-style API (which is still
- supported but not documented in the current release)
-* The [Release Notes](https://github.com/jmcgeheeiv/pyfakefs/blob/master/CHANGES.md)
+* The [Release Notes](https://github.com/pytest-dev/pyfakefs/blob/main/CHANGES.md)
show a list of changes in the latest versions
-### Linking to pyfakefs
-
-In your own documentation, please link to pyfakefs using the canonical URL <http://pyfakefs.org>.
-This URL always points to the most relevant top page for pyfakefs.
-
## Usage
-
-pyfakefs has support for `unittest` and `pytest`, but can also be used
-directly using `fake_filesystem_unittest.Patcher`. Refer to the
-[usage documentation](http://jmcgeheeiv.github.io/pyfakefs/master/usage.html)
-for more information on test scenarios, test customization and
+The simplest method to use pyfakefs is using the `fs` fixture with `pytest`.
+Refer to the
+[usage documentation](https://pytest-pyfakefs.readthedocs.io/en/latest/usage.html)
+for information on other test scenarios, test customization and
using convenience functions.
+## Features
+Apart from automatically mocking most file-system functions, pyfakefs
+provides some additional features:
+- mapping files and directories from the real file system into the fake filesystem
+- configuration and tracking of the file system size
+- pause and resume of patching to be able to use the real file system inside a
+ test step
+- (limited) emulation of other OSes (Linux, macOS or Windows)
+- configuration to behave as if running as a non-root user while running
+ under root
## Compatibility
-pyfakefs works with CPython 3.6 and above, on Linux, Windows and OSX
-(MacOS), and with PyPy3.
+pyfakefs works with CPython 3.8 and above, on Linux, Windows and macOS, and
+with PyPy3.
-pyfakefs works with [pytest](http://doc.pytest.org) version 3.0.0 or above.
+pyfakefs works with [pytest](http://doc.pytest.org) version 3.0.0 or above,
+though a current version is recommended.
pyfakefs will not work with Python libraries that use C libraries to access the
-file system. This is because pyfakefs cannot patch the underlying C libraries'
-file access functions--the C libraries will always access the real file system.
-For example, pyfakefs will not work with [`lxml`](http://lxml.de/). In this case
-`lxml` must be replaced with a pure Python alternative such as
-[`xml.etree.ElementTree`](https://docs.python.org/3/library/xml.etree.elementtree.html).
+file system. This is because pyfakefs cannot patch the underlying C libraries'
+file access functions--the C libraries will always access the real file
+system. Refer to the
+[documentation](https://pytest-pyfakefs.readthedocs.io/en/latest/intro.html#limitations)
+for more information about the limitations of pyfakefs.
## Development
### Continuous integration
-pyfakefs is currently automatically tested on Linux, MacOS and Windows, with
-Python 3.6 to 3.10, and with PyPy3 on Linux, using
-[GitHub Actions](https://github.com/jmcgeheeiv/pyfakefs/actions).
+pyfakefs is currently automatically tested on Linux, macOS and Windows, with
+Python 3.8 to 3.12, and with PyPy3 on Linux, using
+[GitHub Actions](https://github.com/pytest-dev/pyfakefs/actions).
### Running pyfakefs unit tests
#### On the command line
-pyfakefs unit tests can be run using `unittest` or `pytest`:
+pyfakefs unit tests can be run using `pytest` (all tests) or `unittest`
+(all tests except `pytest`-specific ones):
```bash
$ cd pyfakefs/
$ export PYTHONPATH=$PWD
+$ python -m pytest pyfakefs
$ python -m pyfakefs.tests.all_tests
-$ python -m pyfakefs.tests.all_tests_without_extra_packages
-$ python -m pytest pyfakefs/pytest_tests/pytest_plugin_test.py
```
-These scripts are called by `tox` and Travis-CI. `tox` can be used to run tests
-locally against supported python versions:
+Similar scripts are called by `tox` and Github Actions. `tox` can be used to
+run tests locally against supported python versions:
```bash
$ tox
@@ -100,14 +113,14 @@ docker run -t pyfakefs
### Contributing to pyfakefs
We always welcome contributions to the library. Check out the
-[Contributing Guide](https://github.com/jmcgeheeiv/pyfakefs/blob/master/CONTRIBUTING.md)
+[Contributing Guide](https://github.com/pytest-dev/pyfakefs/blob/main/CONTRIBUTING.md)
for more information.
## History
pyfakefs.py was initially developed at Google by Mike Bland as a modest fake
implementation of core Python modules. It was introduced to all of Google
in September 2006. Since then, it has been enhanced to extend its
-functionality and usefulness. At last count, pyfakefs is used in over 2,000
+functionality and usefulness. At last count, pyfakefs was used in over 2,000
Python tests at Google.
Google released pyfakefs to the public in 2011 as Google Code project
@@ -121,5 +134,6 @@ Google released pyfakefs to the public in 2011 as Google Code project
After the [shutdown of Google Code](http://google-opensource.blogspot.com/2015/03/farewell-to-google-code.html)
was announced, [John McGehee](https://github.com/jmcgeheeiv) merged all three Google Code projects together
-[here on GitHub](https://github.com/jmcgeheeiv/pyfakefs) where an enthusiastic community actively supports, maintains
-and extends pyfakefs.
+[here on GitHub](https://github.com/pytest-dev/pyfakefs) where an enthusiastic community actively supports, maintains
+and extends pyfakefs. In 2022, the repository has been transferred to
+[pytest-dev](https://github.com/pytest-dev) to ensure continuous maintenance.
diff --git a/docs/api.rst b/docs/api.rst
deleted file mode 100644
index 9d49ef4..0000000
--- a/docs/api.rst
+++ /dev/null
@@ -1,40 +0,0 @@
-API Notes
-=========
-
-With ``pyfakefs 3.4``, the public API has changed to be PEP-8 conform.
-The old API is deprecated, and will be removed in some future version of
-pyfakefs.
-You can suppress the deprecation warnings for legacy code with the following
-code:
-
-.. code:: python
-
- from pyfakefs.deprecator import Deprecator
-
- Deprecator.show_warnings = False
-
-Here is a list of selected changes:
-
-:pyfakefs.fake_filesystem.FakeFileSystem:
-
- CreateFile() -> create_file()
-
- CreateDirectory() -> create_dir()
-
- CreateLink() -> create_symlink()
-
- GetDiskUsage() -> get_disk_usage()
-
- SetDiskUsage() -> set_disk_usage()
-
-:pyfakefs.fake_filesystem.FakeFile:
-
- GetSize(), SetSize() -> size (property)
-
- SetContents() -> set_contents()
-
- SetATime() -> st_atime (property)
-
- SetMTime() -> st_mtime (property)
-
- SetCTime() -> st_ctime (property)
diff --git a/docs/autopatch.rst b/docs/autopatch.rst
index 66d6a22..c317964 100644
--- a/docs/autopatch.rst
+++ b/docs/autopatch.rst
@@ -11,6 +11,11 @@ The pyfakefs source code contains files that demonstrate this usage model:
- ``example_test.py`` tests ``example.py``. During testing, the pyfakefs fake
file system is used by ``example_test.py`` and ``example.py`` alike.
+.. note:: This example uses the Python ``unittest`` module for testing, but the
+ functionality is similar if using the ``fs`` fixture in ``pytest``,
+ the ``patchfs`` decorator, or the ``Patcher`` class.
+
+
Software Under Test
-------------------
``example.py`` contains a few functions that manipulate files. For instance:
@@ -18,7 +23,7 @@ Software Under Test
.. code:: python
def create_file(path):
- '''Create the specified file and add some content to it. Use the open()
+ """Create the specified file and add some content to it. Use the open()
built in function.
For example, the following file operations occur in the fake file system.
@@ -37,8 +42,8 @@ Software Under Test
>>> with open('/test/file.txt') as f:
... f.readlines()
["This is test file '/test/file.txt'.\\n", 'It was created using the open() function.\\n']
- '''
- with open(path, 'w') as f:
+ """
+ with open(path, "w") as f:
f.write("This is test file '{}'.\n".format(path))
f.write("It was created using the open() function.\n")
@@ -60,6 +65,7 @@ and modules:
import os
import unittest
from pyfakefs import fake_filesystem_unittest
+
# The module under test is example:
import example
@@ -71,7 +77,7 @@ Doctests
.. code:: python
def load_tests(loader, tests, ignore):
- '''Load the pyfakefs/example.py doctest tests into unittest.'''
+ """Load the pyfakefs/example.py doctest tests into unittest."""
return fake_filesystem_unittest.load_doctests(loader, tests, ignore, example)
@@ -89,7 +95,6 @@ Next comes the ``unittest`` test class. This class is derived from
.. code:: python
class TestExample(fake_filesystem_unittest.TestCase):
-
def setUp(self):
self.setUpPyfakefs()
@@ -98,16 +103,16 @@ Next comes the ``unittest`` test class. This class is derived from
pass
def test_create_file(self):
- '''Test example.create_file()'''
+ """Test example.create_file()"""
# The os module has been replaced with the fake os module so all of the
# following occurs in the fake filesystem.
- self.assertFalse(os.path.isdir('/test'))
- os.mkdir('/test')
- self.assertTrue(os.path.isdir('/test'))
+ self.assertFalse(os.path.isdir("/test"))
+ os.mkdir("/test")
+ self.assertTrue(os.path.isdir("/test"))
- self.assertFalse(os.path.exists('/test/file.txt'))
- example.create_file('/test/file.txt')
- self.assertTrue(os.path.exists('/test/file.txt'))
+ self.assertFalse(os.path.exists("/test/file.txt"))
+ example.create_file("/test/file.txt")
+ self.assertTrue(os.path.exists("/test/file.txt"))
...
diff --git a/docs/conf.py b/docs/conf.py
index 73a59d8..d6e0d79 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
#
# pyfakefs documentation build configuration file, created by
# sphinx-quickstart on Mon Oct 31 20:05:53 2016.
@@ -20,8 +19,7 @@
import os
import sys
-sys.path.insert(
- 0, os.path.split(os.path.dirname(os.path.abspath(__file__)))[0])
+sys.path.insert(0, os.path.split(os.path.dirname(os.path.abspath(__file__)))[0])
# -- General configuration ------------------------------------------------
@@ -33,49 +31,49 @@ sys.path.insert(
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
- 'sphinx.ext.autodoc',
- 'sphinx.ext.githubpages', # puts .nojekyll file into source
- 'sphinx.ext.napoleon' # enables google style docstrings
+ "sphinx.ext.autodoc",
+ "sphinx.ext.githubpages", # puts .nojekyll file into source
+ "sphinx.ext.napoleon", # enables google style docstrings
]
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['_templates']
+templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
+source_suffix = ".rst"
# The encoding of source files.
#
# source_encoding = 'utf-8-sig'
# The master toctree document.
-master_doc = 'index'
+master_doc = "index"
# General information about the project.
-project = 'pyfakefs'
-copyright = '''2009 Google Inc. All Rights Reserved.
+project = "pyfakefs"
+copyright = """2009 Google Inc. All Rights Reserved.
© Copyright 2014 Altera Corporation. All Rights Reserved.
-© Copyright 2014-2021 John McGehee'''
-author = 'John McGehee'
+© Copyright 2014-2023 John McGehee"""
+author = "John McGehee"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = '4.6'
+version = "5.3"
# The full version, including alpha/beta/rc tags.
-release = '4.6.dev0'
+release = "5.3.dev0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
-language = None
+language = "en"
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
@@ -89,7 +87,7 @@ language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
-exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
+exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# The reST default role (used for this markup: `text`) to use for all
# documents.
#
@@ -109,12 +107,12 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
#
# show_authors = False
-autoclass_content = 'both'
+autoclass_content = "both"
-autodoc_member_order = 'bysource'
+autodoc_member_order = "bysource"
# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = 'sphinx'
+pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
@@ -130,7 +128,7 @@ todo_include_todos = False
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
-html_theme = 'pyfakefs_theme'
+html_theme = "pyfakefs_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
@@ -139,7 +137,7 @@ html_theme = 'pyfakefs_theme'
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
-html_theme_path = ['.']
+html_theme_path = ["."]
# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
@@ -176,7 +174,7 @@ html_static_path = []
# bottom, using the given strftime format.
# The empty string is equivalent to '%b %d, %Y'.
#
-html_last_updated_fmt = '%b %d, %Y'
+html_last_updated_fmt = "%b %d, %Y"
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
@@ -244,33 +242,38 @@ html_show_sphinx = False
# html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
-htmlhelp_basename = 'pyfakefsdoc'
+htmlhelp_basename = "pyfakefsdoc"
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
- # The paper size ('letterpaper' or 'a4paper').
- #
- # 'papersize': 'letterpaper',
-
- # The font size ('10pt', '11pt' or '12pt').
- #
- # 'pointsize': '10pt',
-
- # Additional stuff for the LaTeX preamble.
- #
- # 'preamble': '',
-
- # Latex figure (float) alignment
- #
- # 'figure_align': 'htbp',
+ # The paper size ('letterpaper' or 'a4paper').
+ #
+ # 'papersize': 'letterpaper',
+ #
+ # The font size ('10pt', '11pt' or '12pt').
+ #
+ # 'pointsize': '10pt',
+ #
+ # Additional stuff for the LaTeX preamble.
+ #
+ # 'preamble': '',
+ #
+ # Latex figure (float) alignment
+ #
+ # 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- (master_doc, 'pyfakefs.tex', 'pyfakefs Documentation',
- 'John McGehee', 'manual'),
+ (
+ master_doc,
+ "pyfakefs.tex",
+ "pyfakefs Documentation",
+ "John McGehee",
+ "manual",
+ ),
]
# The name of an image file (relative to this directory) to place at the top of
@@ -310,10 +313,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
-man_pages = [
- (master_doc, 'pyfakefs', 'pyfakefs Documentation',
- [author], 1)
-]
+man_pages = [(master_doc, "pyfakefs", "pyfakefs Documentation", [author], 1)]
# If true, show URL addresses after external links.
#
@@ -326,9 +326,15 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- (master_doc, 'pyfakefs', 'pyfakefs Documentation',
- author, 'pyfakefs', 'One line description of project.',
- 'Miscellaneous'),
+ (
+ master_doc,
+ "pyfakefs",
+ "pyfakefs Documentation",
+ author,
+ "pyfakefs",
+ "One line description of project.",
+ "Miscellaneous",
+ ),
]
# Documents to append as an appendix to all manuals.
diff --git a/docs/index.rst b/docs/index.rst
index c38273e..dee700b 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -13,13 +13,12 @@ Contents:
intro
usage
+ troubleshooting
autopatch
modules
- api
Indices and tables
==================
* :ref:`genindex`
* :ref:`search`
-
diff --git a/docs/intro.rst b/docs/intro.rst
index 683e132..f022c09 100644
--- a/docs/intro.rst
+++ b/docs/intro.rst
@@ -1,30 +1,31 @@
Introduction
============
-`pyfakefs <https://github.com/jmcgeheeiv/pyfakefs>`__ implements a fake file
+`pyfakefs <https://github.com/pytest-dev/pyfakefs>`__ implements a fake file
system that mocks the Python file system modules.
Using pyfakefs, your tests operate on a fake file system in memory without touching the real disk.
The software under test requires no modification to work with pyfakefs.
-pyfakefs works with CPython 3.6 and above, on Linux, Windows and OSX
-(MacOS), and with PyPy3.
+pyfakefs works with CPython 3.8 and above, on Linux, Windows and macOS,
+and with PyPy3.
-pyfakefs works with `pytest <doc.pytest.org>`__ version 3.0.0 or above.
+pyfakefs works with `pytest <doc.pytest.org>`__ version 3.0.0 or above by
+providing the `fs` fixture that enables the fake filesystem.
Installation
------------
-pyfakefs is available on `PyPi <https://pypi.python.org/pypi/pyfakefs/>`__.
-The latest released version can be installed from pypi:
+pyfakefs is available on `PyPI <https://pypi.python.org/pypi/pyfakefs/>`__.
+The latest released version can be installed from PyPI:
.. code:: bash
pip install pyfakefs
-The latest master can be installed from the GitHub sources:
+The latest main can be installed from the GitHub sources:
.. code:: bash
- pip install git+https://github.com/jmcgeheeiv/pyfakefs
+ pip install git+https://github.com/pytest-dev/pyfakefs
Features
--------
@@ -33,9 +34,9 @@ Features
the real filesystem will work on the fake filesystem if running under
pyfakefs.
-- pyfakefs provides direct support for `unittest` (via a `TestCase` base
- class) and `pytest` (via a fixture), but can also be used with other test
- frameworks.
+- pyfakefs provides direct support for `pytest` (via the `fs` fixture)
+ and `unittest` (via a `TestCase` base class), but can also be used with
+ other test frameworks.
- Each pyfakefs test starts with an empty file system, but it is possible to
map files and directories from the real file system into the fake
@@ -51,7 +52,7 @@ Features
real file system has to be used in a test step
- pyfakefs defaults to the OS it is running on, but can also be configured
- to test code running under another OS (Linux, MacOS or Windows).
+ to test code running under another OS (Linux, macOS or Windows).
- pyfakefs can be configured to behave as if running as a root or as a
non-root user, independently from the actual user.
@@ -77,18 +78,22 @@ Limitations
Python implementations will probably not work
- Differences in the behavior in different Linux distributions or different
- MacOS or Windows versions may not be reflected in the implementation, as
+ macOS or Windows versions may not be reflected in the implementation, as
well as some OS-specific low-level file system behavior. The systems used
- for automatic tests in
- `Travis.CI <https://travis-ci.org/jmcgeheeiv/pyfakefs>`__ and
- `AppVeyor <https://ci.appveyor.com/project/jmcgeheeiv/pyfakefs>`__ are
- considered as reference systems, additionally the tests are run in Docker
+ for automatic tests in GitHub Actions are
+ considered as reference systems. Additionally, the tests are run in Docker
containers with the latest CentOS, Debian, Fedora and Ubuntu images.
- pyfakefs may not work correctly if file system functions are patched by
other means (e.g. using `unittest.mock.patch`) - see
:ref:`usage_with_mock_open` for more information
+- pyfakefs will not work correctly with
+ `behave <https://github.com/behave/behave>`__ due to the way it loads
+ the steps, if any filesystem modules are imported globally in the steps or
+ environment files; as a workaround, you may load them locally inside the
+ test steps (see `this issue <https://github.com/pytest-dev/pyfakefs/issues/703>`__)
+
History
-------
pyfakefs was initially developed at Google by
@@ -111,5 +116,7 @@ After the `shutdown of Google
Code <http://google-opensource.blogspot.com/2015/03/farewell-to-google-code.html>`__
was announced, `John McGehee <https://github.com/jmcgeheeiv>`__ merged
all three Google Code projects together `on
-GitHub <https://github.com/jmcgeheeiv/pyfakefs>`__ where an enthusiastic
-community actively maintains and extends pyfakefs.
+GitHub <https://github.com/pytest-dev/pyfakefs>`__ where an enthusiastic
+community actively maintains and extends pyfakefs. In 2022, the repository has
+been transferred to `pytest-dev <https://github.com/pytest-dev>`__ to ensure
+continuous maintenance.
diff --git a/docs/modules.rst b/docs/modules.rst
index 4fa020f..75c96bf 100644
--- a/docs/modules.rst
+++ b/docs/modules.rst
@@ -6,8 +6,8 @@ Public Modules and Classes
Fake filesystem module
----------------------
-.. automodule:: pyfakefs.fake_filesystem
- :members: set_uid, set_gid
+.. automodule:: pyfakefs.helpers
+ :members: get_uid, set_uid, get_gid, set_gid, reset_ids, is_root
Fake filesystem classes
-----------------------
@@ -18,11 +18,11 @@ Fake filesystem classes
create_dir, create_file, create_symlink,
get_object, pause, resume
-.. autoclass:: pyfakefs.fake_filesystem.FakeFile
+.. autoclass:: pyfakefs.fake_file.FakeFile
:members: byte_contents, contents, set_contents,
path, size, is_large_file
-.. autoclass:: pyfakefs.fake_filesystem.FakeDirectory
+.. autoclass:: pyfakefs.fake_file.FakeDirectory
:members: contents, ordered_dirs, size, get_entry, remove_entry
Unittest module classes
@@ -43,13 +43,13 @@ Unittest module classes
Faked module classes
--------------------
-.. autoclass:: pyfakefs.fake_filesystem.FakeOsModule
+.. autoclass:: pyfakefs.fake_os.FakeOsModule
-.. autoclass:: pyfakefs.fake_filesystem.FakePathModule
+.. autoclass:: pyfakefs.fake_path.FakePathModule
-.. autoclass:: pyfakefs.fake_filesystem.FakeFileOpen
+.. autoclass:: pyfakefs.fake_open.FakeFileOpen
-.. autoclass:: pyfakefs.fake_filesystem.FakeIoModule
+.. autoclass:: pyfakefs.fake_io.FakeIoModule
.. autoclass:: pyfakefs.fake_filesystem_shutil.FakeShutilModule
diff --git a/docs/pyfakefs_theme/static/pyfakefs.css b/docs/pyfakefs_theme/static/pyfakefs.css
index 8c00229..0ab879b 100644
--- a/docs/pyfakefs_theme/static/pyfakefs.css
+++ b/docs/pyfakefs_theme/static/pyfakefs.css
@@ -7,4 +7,3 @@
.highlight pre {
background-color: #F5F5F5;
}
-
diff --git a/docs/troubleshooting.rst b/docs/troubleshooting.rst
new file mode 100644
index 0000000..ba2b977
--- /dev/null
+++ b/docs/troubleshooting.rst
@@ -0,0 +1,245 @@
+Troubleshooting
+===============
+This is a collection of problems with ``pyfakefs`` and possible solutions.
+It will be expanded continuously based on issues and problems found by users.
+
+Modules not working with pyfakefs
+---------------------------------
+
+Modules may not work with ``pyfakefs`` for several reasons. ``pyfakefs``
+works by patching some file system related modules and functions, specifically:
+
+- most file system related functions in the ``os`` and ``os.path`` modules
+- the ``pathlib`` module
+- the built-in ``open`` function and ``io.open``
+- ``shutil.disk_usage``
+
+Other file system related modules work with ``pyfakefs``, because they use
+exclusively these patched functions, specifically ``shutil`` (except for
+``disk_usage``), ``tempfile``, ``glob`` and ``zipfile``.
+
+A module may not work with ``pyfakefs`` because of one of the following
+reasons:
+
+- It uses a file system related function of the mentioned modules that is
+ not or not correctly patched. Mostly these are functions that are seldom
+ used, but may be used in Python libraries (this has happened for example
+ with a changed implementation of ``shutil`` in Python 3.7). Generally,
+ these shall be handled in issues and we are happy to fix them.
+- It uses file system related functions in a way that will not be patched
+ automatically. This is the case for functions that are executed while
+ reading a module. This case and a possibility to make them work is
+ documented above under ``modules_to_reload``.
+- It uses OS specific file system functions not contained in the Python
+ libraries. These will not work out of the box, and we generally will not
+ support them in ``pyfakefs``. If these functions are used in isolated
+ functions or classes, they may be patched by using the ``modules_to_patch``
+ parameter (see the example for file locks in Django above), or by using
+ ``unittest.patch`` if you don't need to simulate the functions. We
+ added some of these patches to ``pyfakefs``, so that they are applied
+ automatically (currently done for some ``pandas`` and ``Django``
+ functionality).
+- It uses C libraries to access the file system. There is no way no make
+ such a module work with ``pyfakefs``--if you want to use it, you
+ have to patch the whole module. In some cases, a library implemented in
+ Python with a similar interface already exists. An example is ``lxml``,
+ which can be substituted with ``ElementTree`` in most cases for testing.
+
+A list of Python modules that are known to not work correctly with
+``pyfakefs`` will be collected here:
+
+`multiprocessing`_ (built-in)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This module has several issues (related to points 1 and 3 above).
+Currently there are no plans to fix this, but this may change in case of
+sufficient demand.
+
+`subprocess`_ (built-in)
+~~~~~~~~~~~~~~~~~~~~~~~~
+This has very similar problems to ``multiprocessing`` and cannot be used with
+``pyfakefs`` to start a process. ``subprocess`` can either be mocked, if
+the process is not needed for the test, or patching can be paused to start
+a process if needed, and resumed afterwards
+(see `this issue <https://github.com/pytest-dev/pyfakefs/issues/447>`__).
+
+Modules that rely on ``subprocess`` or ``multiprocessing``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This includes a number of modules that need to start other executables to
+function correctly. Examples that have shown this problem include `GitPython`_
+and `plumbum`_. Calling ``find_library`` also uses ``subprocess`` and does not work in
+the fake filesystem.
+
+`sqlite3`_ (built-in)
+~~~~~~~~~~~~~~~~~~~~~~~~
+This is a database adapter written in C, which uses the database C API to access files.
+This (and similar database adapters) will not work with ``pyfakefs``, as it will always
+access the real filesystem.
+
+The `Pillow`_ Imaging Library
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This library partly works with ``pyfakefs``, but it is known to not work at
+least if writing JPEG files
+(see `this issue <https://github.com/pytest-dev/pyfakefs/issues/529>`__)
+
+The `pandas`_ data analysis toolkit
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This uses its own internal file system access written in C, thus much of
+``pandas`` will not work with ``pyfakefs`` out of the box. Having said that,
+``pyfakefs`` patches ``pandas`` to use standard file-system access instead,
+so that many of the ``read_xxx`` functions, including ``read_csv`` and
+``read_excel``, as well as some writer functions, do work with the fake file
+system. If you use only these functions, ``pyfakefs`` should work fine with
+``pandas``.
+
+`xlrd`_
+~~~~~~~
+This library is used by ``pandas`` to read Excel files in the `.xls` format,
+and can also be used stand-alone. Similar to ``pandas``, it is by default
+patched by ``pyfakefs`` to use normal file system functions that can be
+patched.
+
+`openpyxl`_
+~~~~~~~~~~~
+This is another library that reads and writes Excel files, and is also
+used by ``pandas`` if installed. ``openpyxl`` uses ``lxml`` for some file-system
+access if it is installed--in this case ``pyfakefs`` will not be able to patch
+it correctly (``lxml`` uses C functions for file system access). It will `not`
+use ``lxml`` however, if the environment variable ``OPENPYXL_LXML`` is set to
+"False" (or anything other than "True"), so if you set this variable `before`
+running the tests, it can work fine with ``pyfakefs``.
+
+If you encounter a module not working with ``pyfakefs``, and you are not sure
+if the module can be handled or how to do it, please write a new issue. We
+will check if it can be made to work, and at least add it to this list.
+
+Pyfakefs behaves differently than the real filesystem
+-----------------------------------------------------
+There are at least the following kinds of deviations from the actual behavior:
+
+- unwanted deviations that we didn't notice--if you find any of these, please
+ write an issue and we will try to fix it
+- behavior that depends on different OS versions and editions--as mentioned
+ in :ref:`limitations`, ``pyfakefs`` uses the systems used for CI tests in
+ GitHub Actions as reference system and will not replicate all system-specific behavior
+- behavior that depends on low-level OS functionality that ``pyfakefs`` is not
+ able to emulate; examples are the ``fcntl.ioctl`` and ``fcntl.fcntl``
+ functions that are patched to do nothing
+
+The test code tries to access files in the real filesystem
+----------------------------------------------------------
+The loading of the actual Python code from the real filesystem does not use
+the filesystem functions that ``pyfakefs`` patches, but in some cases it may
+access other files in the packages. An example is loading timezone information
+from configuration files. In these cases, you have to map the respective files
+or directories from the real into the fake filesystem as described in
+:ref:`real_fs_access`.
+
+If you are using Django, various dependencies may expect both the project
+directory and the ``site-packages`` installation to exist in the fake filesystem.
+
+Here's an example of how to add these using pytest::
+
+
+ import os
+ import django
+ import pytest
+
+ @pytest.fixture
+ def fake_fs(fs):
+ PROJECT_BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+ fs.add_real_paths(
+ [
+ PROJECT_BASE_DIR,
+ os.path.dirname(django.__file__),
+ ]
+ )
+ return fs
+
+OS temporary directories
+------------------------
+Tests relying on a completely empty file system on test start will fail.
+As ``pyfakefs`` does not fake the ``tempfile`` module (as described above),
+a temporary directory is required to ensure that ``tempfile`` works correctly,
+e.g., that ``tempfile.gettempdir()`` will return a valid value. This
+means that any newly created fake file system will always have either a
+directory named ``/tmp`` when running on Linux or Unix systems,
+``/var/folders/<hash>/T`` when running on macOS, or
+``C:\Users\<user>\AppData\Local\Temp`` on Windows:
+
+.. code:: python
+
+ import os
+
+
+ def test_something(fs):
+ # the temp directory is always present at test start
+ assert len(os.listdir("/")) == 1
+
+Under macOS and linux, if the actual temp path is not `/tmp` (which is always the case
+under macOS), a symlink to the actual temp directory is additionally created as `/tmp`
+in the fake filesystem. Note that the file size of this link is ignored while
+calculating the fake filesystem size, so that the used size with an otherwise empty
+fake filesystem can always be assumed to be 0.
+
+
+User rights
+-----------
+If you run ``pyfakefs`` tests as root (this happens by default if run in a
+docker container), ``pyfakefs`` also behaves as a root user, for example can
+write to write-protected files. This may not be the expected behavior, and
+can be changed.
+``Pyfakefs`` has a rudimentary concept of user rights, which differentiates
+between root user (with the user id 0) and any other user. By default,
+``pyfakefs`` assumes the user id of the current user, but you can change
+that using ``pyfakefs.helpers.set_uid()`` in your setup. This allows to run
+tests as non-root user in a root user environment and vice verse.
+Another possibility to run tests as non-root user in a root user environment
+is the convenience argument :ref:`allow_root_user`:
+
+.. code:: python
+
+ from pyfakefs.fake_filesystem_unittest import TestCase
+
+
+ class SomeTest(TestCase):
+ def setUp(self):
+ self.setUpPyfakefs(allow_root_user=False)
+
+
+.. _usage_with_mock_open:
+
+Pyfakefs and mock_open
+----------------------
+If you patch ``open`` using ``mock_open`` before the initialization of
+``pyfakefs``, it will not work properly, because the ``pyfakefs``
+initialization relies on ``open`` working correctly.
+Generally, you should not need ``mock_open`` if using ``pyfakefs``, because you
+always can create the files with the needed content using ``create_file``.
+This is true for patching any filesystem functions--avoid patching them
+while working with ``pyfakefs``.
+If you still want to use ``mock_open``, make sure it is only used while
+patching is in progress. For example, if you are using ``pytest`` with the
+``mocker`` fixture used to patch ``open``, make sure that the ``fs`` fixture is
+passed before the ``mocker`` fixture to ensure this:
+
+.. code:: python
+
+ def test_mock_open_incorrect(mocker, fs):
+ # causes a recursion error
+ mocker.patch("builtins.open", mocker.mock_open(read_data="content"))
+
+
+ def test_mock_open_correct(fs, mocker):
+ # works correctly
+ mocker.patch("builtins.open", mocker.mock_open(read_data="content"))
+
+
+.. _`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
+.. _`GitPython`: https://pypi.org/project/GitPython/
+.. _`plumbum`: https://pypi.org/project/plumbum/
+.. _`Pillow`: https://pypi.org/project/Pillow/
+.. _`pandas`: https://pypi.org/project/pandas/
+.. _`xlrd`: https://pypi.org/project/xlrd/
+.. _`openpyxl`: https://pypi.org/project/openpyxl/
diff --git a/docs/usage.rst b/docs/usage.rst
index b2ec2fa..f90377f 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -5,6 +5,50 @@ Test Scenarios
--------------
There are several approaches for implementing tests using ``pyfakefs``.
+Patch using the pytest plugin
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+``pyfakefs`` functions as a `pytest`_ plugin that provides the `fs` fixture,
+which is registered at installation time.
+Using this fixture automatically patches all file system functions with
+the fake file system functions. It also allows to access several
+convenience methods (see :ref:`convenience_methods`).
+
+Here is an example for a simple test:
+
+.. code:: python
+
+ def my_fakefs_test(fs):
+ # "fs" is the reference to the fake file system
+ fs.create_file("/var/data/xx1.txt")
+ assert os.path.exists("/var/data/xx1.txt")
+
+If you are bothered by the ``pylint`` warning,
+``C0103: Argument name "fs" doesn't conform to snake_case naming style
+(invalid-name)``,
+you can define a longer name in your ``conftest.py`` and use that in your
+tests:
+
+.. code:: python
+
+ @pytest.fixture
+ def fake_filesystem(fs): # pylint:disable=invalid-name
+ """Variable name 'fs' causes a pylint warning. Provide a longer name
+ acceptable to pylint for use in tests.
+ """
+ yield fs
+
+Class-, module- and session-scoped fixtures
+...........................................
+For convenience, class-, module- and session-scoped fixtures with the same
+functionality are provided, named ``fs_class``, ``fs_module`` and ``fs_session``,
+respectively.
+
+.. caution:: If any of these fixtures is active, any other ``fs`` fixture will
+ not setup / tear down the fake filesystem in the current scope; instead, it
+ will just serve as a reference to the active fake filesystem. That means that changes
+ done in the fake filesystem inside a test will remain there until the respective scope
+ ends.
+
Patch using fake_filesystem_unittest
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you are using the Python ``unittest`` package, the easiest approach is to
@@ -18,12 +62,13 @@ with the fake file system functions and modules:
from pyfakefs.fake_filesystem_unittest import TestCase
+
class ExampleTestCase(TestCase):
def setUp(self):
self.setUpPyfakefs()
def test_create_file(self):
- file_path = '/test/file.txt'
+ file_path = "/test/file.txt"
self.assertFalse(os.path.exists(file_path))
self.fs.create_file(file_path)
self.assertTrue(os.path.exists(file_path))
@@ -31,38 +76,40 @@ with the fake file system functions and modules:
The usage is explained in more detail in :ref:`auto_patch` and
demonstrated in the files `example.py`_ and `example_test.py`_.
-Patch using the pytest plugin
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If you use `pytest`_, you will be interested in the pytest plugin in
-``pyfakefs``.
-This automatically patches all file system functions and modules in a
-similar manner as described above.
-
-The pytest plugin provides the ``fs`` fixture for use in your test. The plugin
-is registered for pytest on installing ``pyfakefs`` as usual for pytest
-plugins, so you can just use it:
+If your setup is the same for all tests in a class, you can use the class setup
+method ``setUpClassPyfakefs`` instead:
.. code:: python
- def my_fakefs_test(fs):
- # "fs" is the reference to the fake file system
- fs.create_file('/var/data/xx1.txt')
- assert os.path.exists('/var/data/xx1.txt')
+ from pyfakefs.fake_filesystem_unittest import TestCase
-If you are bothered by the ``pylint`` warning,
-``C0103: Argument name "fs" doesn't conform to snake_case naming style
-(invalid-name)``,
-you can define a longer name in your ``conftest.py`` and use that in your
-tests:
-.. code:: python
+ class ExampleTestCase(TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.setUpClassPyfakefs()
+ # setup the fake filesystem using standard functions
+ pathlib.Path("/test/file1.txt").touch()
+ # you can also access the fake fs via fake_fs() if needed
+ cls.fake_fs().create_file("/test/file2.txt", contents="test")
+
+ def test1(self):
+ self.assertTrue(os.path.exists("/test/file1.txt"))
+ self.assertTrue(os.path.exists("/test/file2.txt"))
+
+ def test2(self):
+ self.assertTrue(os.path.exists("/test/file1.txt"))
+ file_path = "/test/file3.txt"
+ # self.fs is the same instance as cls.fake_fs() above
+ self.fs.create_file(file_path)
+ self.assertTrue(os.path.exists(file_path))
- @pytest.fixture
- def fake_filesystem(fs): # pylint:disable=invalid-name
- """Variable name 'fs' causes a pylint warning. Provide a longer name
- acceptable to pylint for use in tests.
- """
- yield fs
+.. note:: This feature cannot be used with a Python version before Python 3.8 due to
+ a missing feature in ``unittest``.
+
+.. caution:: If this is used, any changes made in the fake filesystem inside a test
+ will remain there for all following tests in the test class, if they are not reverted
+ in the test itself.
Patch using fake_filesystem_unittest.Patcher
@@ -80,10 +127,10 @@ The easiest way is to just use ``Patcher`` as a context manager:
with Patcher() as patcher:
# access the fake_filesystem object via patcher.fs
- patcher.fs.create_file('/foo/bar', contents='test')
+ patcher.fs.create_file("/foo/bar", contents="test")
# the following code works on the fake filesystem
- with open('/foo/bar') as f:
+ with open("/foo/bar") as f:
contents = f.read()
You can also initialize ``Patcher`` manually:
@@ -93,7 +140,7 @@ You can also initialize ``Patcher`` manually:
from pyfakefs.fake_filesystem_unittest import Patcher
patcher = Patcher()
- patcher.setUp() # called in the initialization code
+ patcher.setUp() # called in the initialization code
...
patcher.tearDown() # somewhere in the cleanup code
@@ -107,10 +154,11 @@ single function, you can write:
from pyfakefs.fake_filesystem_unittest import patchfs
+
@patchfs
def test_something(fake_fs):
# access the fake_filesystem object via fake_fs
- fake_fs.create_file('/foo/bar', contents='test')
+ fake_fs.create_file("/foo/bar", contents="test")
Note that ``fake_fs`` is a positional argument and the argument name does
not matter. If there are additional ``mock.patch`` decorators that also
@@ -120,11 +168,12 @@ order, as shown here:
.. code:: python
@patchfs
- @mock.patch('foo.bar')
+ @mock.patch("foo.bar")
def test_something(fake_fs, mocked_bar):
...
- @mock.patch('foo.bar')
+
+ @mock.patch("foo.bar")
@patchfs
def test_something(mocked_bar, fake_fs):
...
@@ -146,10 +195,9 @@ You can also use this to make a single unit test use the fake fs:
.. code:: python
class TestSomething(unittest.TestCase):
-
@patchfs
def test_something(self, fs):
- fs.create_file('/foo/bar', contents='test')
+ fs.create_file("/foo/bar", contents="test")
.. _customizing_patcher:
@@ -178,23 +226,6 @@ constructor:
with Patcher(allow_root_user=False) as patcher:
...
-Unittest
-........
-If you are using ``fake_filesystem_unittest.TestCase``, the arguments can be
-passed to ``setUpPyfakefs()``, which will pass them to the ``Patcher``
-instance:
-
-.. code:: python
-
- from pyfakefs.fake_filesystem_unittest import TestCase
-
- class SomeTest(TestCase):
- def setUp(self):
- self.setUpPyfakefs(allow_root_user=False)
-
- def testSomething(self):
- ...
-
Pytest
......
@@ -208,11 +239,13 @@ In case of ``pytest``, you have two possibilities:
import pytest
from pyfakefs.fake_filesystem_unittest import Patcher
+
@pytest.fixture
def fs_no_root():
with Patcher(allow_root_user=False) as patcher:
yield patcher.fs
+
def test_something(fs_no_root):
...
@@ -226,10 +259,28 @@ In case of ``pytest``, you have two possibilities:
import pytest
- @pytest.mark.parametrize('fs', [[None, None, None, False]], indirect=True)
+
+ @pytest.mark.parametrize("fs", [[None, None, None, False]], indirect=True)
def test_something(fs):
...
+Unittest
+........
+If you are using ``fake_filesystem_unittest.TestCase``, the arguments can be
+passed to ``setUpPyfakefs()``, which will pass them to the ``Patcher``
+instance:
+
+.. code:: python
+
+ from pyfakefs.fake_filesystem_unittest import TestCase
+
+
+ class SomeTest(TestCase):
+ def setUp(self):
+ self.setUpPyfakefs(allow_root_user=False)
+
+ def testSomething(self):
+ ...
patchfs
.......
@@ -240,6 +291,7 @@ the decorator:
from pyfakefs.fake_filesystem_unittest import patchfs
+
@patchfs(allow_root_user=False)
def test_something(fake_fs):
...
@@ -307,6 +359,7 @@ automatically due to performance reasons (though it can be switched on using
import os
+
def check_if_exists(filepath, file_exists=os.path.exists):
return file_exists(filepath)
@@ -328,8 +381,9 @@ an example from a related issue):
import pathlib
+
@click.command()
- @click.argument('foo', type=click.Path(path_type=pathlib.Path))
+ @click.argument("foo", type=click.Path(path_type=pathlib.Path))
def hello(foo):
pass
@@ -353,32 +407,40 @@ the file ``example/sut.py``, the following code will work:
self.setUpPyfakefs(modules_to_reload=[example.sut])
def test_path_exists(self):
- file_path = '/foo/bar'
+ file_path = "/foo/bar"
self.fs.create_dir(file_path)
self.assertTrue(example.sut.check_if_exists(file_path))
+
# example using pytest
- @pytest.mark.parametrize('fs', [[None, [example.sut]]], indirect=True)
+ @pytest.mark.parametrize("fs", [[None, [example.sut]]], indirect=True)
def test_path_exists(fs):
- file_path = '/foo/bar'
+ file_path = "/foo/bar"
fs.create_dir(file_path)
assert example.sut.check_if_exists(file_path)
+
# example using Patcher
def test_path_exists():
with Patcher(modules_to_reload=[example.sut]) as patcher:
- file_path = '/foo/bar'
- patcher.fs.create_dir(file_path)
- assert example.sut.check_if_exists(file_path)
+ file_path = "/foo/bar"
+ patcher.fs.create_dir(file_path)
+ assert example.sut.check_if_exists(file_path)
+
# example using patchfs decorator
@patchfs(modules_to_reload=[example.sut])
def test_path_exists(fs):
- file_path = '/foo/bar'
+ file_path = "/foo/bar"
fs.create_dir(file_path)
assert example.sut.check_if_exists(file_path)
+.. note:: If the reloaded modules depend on each other (e.g. one imports the other),
+ the order in which they are reloaded matters. The dependent module should be reloaded
+ first, so that on reloading the depending module it is already correctly patched.
+
+
modules_to_patch
................
Sometimes there are file system modules in other packages that are not
@@ -396,6 +458,7 @@ has now been been integrated into ``pyfakefs``):
class FakeLocks:
"""django.core.files.locks uses low level OS functions, fake it."""
+
_locks_module = django.core.files.locks
def __init__(self, fs):
@@ -416,27 +479,31 @@ has now been been integrated into ``pyfakefs``):
def __getattr__(self, name):
return getattr(self._locks_module, name)
+
...
# test code using Patcher
- with Patcher(modules_to_patch={'django.core.files.locks': FakeLocks}):
+ with Patcher(modules_to_patch={"django.core.files.locks": FakeLocks}):
test_django_stuff()
# test code using unittest
class TestUsingDjango(fake_filesystem_unittest.TestCase):
def setUp(self):
- self.setUpPyfakefs(modules_to_patch={'django.core.files.locks': FakeLocks})
+ self.setUpPyfakefs(modules_to_patch={"django.core.files.locks": FakeLocks})
- def test_django_stuff(self)
+ def test_django_stuff(self):
...
+
# test code using pytest
- @pytest.mark.parametrize('fs', [[None, None,
- {'django.core.files.locks': FakeLocks}]], indirect=True)
+ @pytest.mark.parametrize(
+ "fs", [[None, None, {"django.core.files.locks": FakeLocks}]], indirect=True
+ )
def test_django_stuff(fs):
...
+
# test code using patchfs decorator
- @patchfs(modules_to_patch={'django.core.files.locks': FakeLocks})
+ @patchfs(modules_to_patch={"django.core.files.locks": FakeLocks})
def test_django_stuff(fake_fs):
...
@@ -450,8 +517,8 @@ can be added to ``additional_skip_names``:
.. code:: python
- with Patcher(additional_skip_names=['pydevd']) as patcher:
- patcher.fs.create_file('foo')
+ with Patcher(additional_skip_names=["pydevd"]) as patcher:
+ patcher.fs.create_file("foo")
Alternatively to the module names, the modules themselves may be used:
@@ -460,7 +527,7 @@ Alternatively to the module names, the modules themselves may be used:
import pydevd
with Patcher(additional_skip_names=[pydevd]) as patcher:
- patcher.fs.create_file('foo')
+ patcher.fs.create_file("foo")
.. _allow_root_user:
@@ -499,6 +566,7 @@ set ``patch_open_code`` to ``PatchMode.AUTO``:
from pyfakefs.fake_filesystem_unittest import PatchMode
+
@patchfs(patch_open_code=PatchMode.AUTO)
def test_something(fs):
...
@@ -517,6 +585,7 @@ system function is not patched automatically:
import os
+
def check_if_exists(filepath, file_exists=os.path.exists):
return file_exists(filepath)
@@ -526,12 +595,37 @@ search for this kind of default arguments and patch them automatically.
You could also use the :ref:`modules_to_reload` option with the module that
contains the default argument instead, if you want to avoid the overhead.
+.. note:: There are some cases where this option dees not work:
+
+ - if default arguments are *computed* using file system functions:
+
+ .. code:: python
+
+ import os
+
+
+ def some_function(use_bar=os.path.exists("/foo/bar")):
+ return do_something() if use_bar else do_something_else()
+
+ - if the default argument is an instance of ``pathlib.Path``:
+
+ .. code:: python
+
+ import pathlib
+
+
+ def foobar(dir_arg=pathlib.Path.cwd() / "logs"):
+ do_something(dir_arg)
+
+ In both cases the default arguments behave like global variables that use a file system function
+ (which they basically are), and can only be handled using :ref:`modules_to_reload`.
+
+
use_cache
.........
If True (the default), patched and non-patched modules are cached between tests
to avoid the performance hit of the file system function lookup (the
-patching itself is reverted after each test). As this is a new
-feature, this argument allows to turn it off in case it causes any problems:
+patching itself is reverted after each test). This argument allows to turn it off in case it causes any problems:
.. code:: python
@@ -540,9 +634,22 @@ feature, this argument allows to turn it off in case it causes any problems:
fake_fs.create_file("foo", contents="test")
...
-Please write an issue if you encounter any problem that can be fixed by using
-this parameter. Note that this argument may be removed in a later version, if
-no problems come up.
+If using ``pytest``, the cache is always cleared before the final test shutdown, as there has been a problem
+happening on shutdown related to removing the cached modules.
+This does not happen for other test methods so far.
+
+If you think you have encountered a similar problem with ``unittest``, you may try to clear the cache
+during module shutdown using the class method for clearing the cache:
+
+.. code:: python
+
+ from pyfakefs.fake_filesystem_unittest import Patcher
+
+
+ def tearDownModule():
+ Patcher.clear_fs_cache()
+
+Please write an issue if you encounter any problem that can be fixed by using this parameter.
If you want to clear the cache just for a specific test instead, you can call
``clear_cache`` on the ``Patcher`` or the ``fake_filesystem`` instance:
@@ -554,6 +661,8 @@ If you want to clear the cache just for a specific test instead, you can call
...
+.. _convenience_methods:
+
Using convenience methods
-------------------------
While ``pyfakefs`` can be used just with the standard Python file system
@@ -579,15 +688,16 @@ with large files, see also :ref:`set-fs-size`).
from pyfakefs.fake_filesystem_unittest import TestCase
+
class ExampleTestCase(TestCase):
def setUp(self):
self.setUpPyfakefs()
def test_create_file(self):
- file_path = '/foo/bar/test.txt'
- self.fs.create_file(file_path, contents = 'test')
+ file_path = "/foo/bar/test.txt"
+ self.fs.create_file(file_path, contents="test")
with open(file_path) as f:
- self.assertEqual('test', f.read())
+ self.assertEqual("test", f.read())
``create_dir()`` behaves like ``os.makedirs()``.
``create_symlink`` and ``create_link`` behave like ``os.symlink`` and
@@ -598,6 +708,8 @@ automatically.
The first two arguments in ``create_symlink`` are reverted in relation to
``os.symlink`` for historical reasons.
+.. _real_fs_access:
+
Access to files in the real file system
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you want to have read access to real files or directories, you can map
@@ -619,16 +731,18 @@ fake filesystem via the argument ``target_path``.
from pyfakefs.fake_filesystem_unittest import TestCase
+
class ExampleTestCase(TestCase):
- fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures')
+ fixture_path = os.path.join(os.path.dirname(__file__), "fixtures")
+
def setUp(self):
self.setUpPyfakefs()
# make the file accessible in the fake file system
self.fs.add_real_directory(self.fixture_path)
- def test_using_fixture1(self):
- with open(os.path.join(self.fixture_path, 'fixture1.txt') as f:
+ def test_using_fixture(self):
+ with open(os.path.join(self.fixture_path, "fixture1.txt")) as f:
# file contents are copied to the fake file system
# only at this point
contents = f.read()
@@ -640,17 +754,25 @@ You can do the same using ``pytest`` by using a fixture for test setup:
import pytest
import os
- fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures')
+ fixture_path = os.path.join(os.path.dirname(__file__), "fixtures")
+
@pytest.fixture
def my_fs(fs):
fs.add_real_directory(fixture_path)
yield fs
- def test_using_fixture1(my_fs):
- with open(os.path.join(fixture_path, 'fixture1.txt') as f:
+
+ @pytest.mark.usefixtures("my_fs")
+ def test_using_fixture():
+ with open(os.path.join(fixture_path, "fixture1.txt")) as f:
contents = f.read()
+.. note::
+ If you are not using the fixture directly in the test, you can use
+ ``@pytest.mark.usefixtures`` instead of passing the fixture as an argument.
+ This avoids warnings about unused arguments from linters.
+
When using ``pytest`` another option is to load the contents of the real file
in a fixture and pass this fixture to the test function **before** passing
the ``fs`` fixture.
@@ -660,13 +782,15 @@ the ``fs`` fixture.
import pytest
import os
+
@pytest.fixture
def content():
- fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures')
- with open(os.path.join(fixture_path, 'fixture1.txt') as f:
+ fixture_path = os.path.join(os.path.dirname(__file__), "fixtures")
+ with open(os.path.join(fixture_path, "fixture1.txt")) as f:
contents = f.read()
return contents
+
def test_using_file_contents(content, fs):
fs.create_file("fake/path.txt")
assert content != ""
@@ -674,7 +798,7 @@ the ``fs`` fixture.
Handling mount points
~~~~~~~~~~~~~~~~~~~~~
-Under Linux and MacOS, the root path (``/``) is the only mount point created
+Under Linux and macOS, the root path (``/``) is the only mount point created
in the fake file system. If you need support for more mount points, you can add
them using ``add_mount_point()``.
@@ -707,16 +831,16 @@ and you may fail to create new files if the fake file system is full.
from pyfakefs.fake_filesystem_unittest import TestCase
- class ExampleTestCase(TestCase):
+ class ExampleTestCase(TestCase):
def setUp(self):
self.setUpPyfakefs()
self.fs.set_disk_usage(100)
def test_disk_full(self):
- with open('/foo/bar.txt', 'w') as f:
+ with open("/foo/bar.txt", "w") as f:
with self.assertRaises(OSError):
- f.write('a' * 200)
+ f.write("a" * 200)
f.flush()
To get the file system size, you may use ``get_disk_usage()``, which is
@@ -737,6 +861,7 @@ Here is an example that tests the usage with the ``pyfakefs`` pytest fixture:
from pyfakefs.fake_filesystem_unittest import Pause
+
def test_pause_resume_contextmanager(fs):
fake_temp_file = tempfile.NamedTemporaryFile()
assert os.path.exists(fake_temp_file.name)
@@ -754,6 +879,7 @@ Here is the same code using a context manager:
from pyfakefs.fake_filesystem_unittest import Pause
+
def test_pause_resume_contextmanager(fs):
fake_temp_file = tempfile.NamedTemporaryFile()
assert os.path.exists(fake_temp_file.name)
@@ -766,7 +892,7 @@ Here is the same code using a context manager:
Simulating other file systems
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-``Pyfakefs`` supports Linux, MacOS and Windows operating systems. By default,
+``Pyfakefs`` supports Linux, macOS and Windows operating systems. By default,
the file system of the OS where the tests run is assumed, but it is possible
to simulate other file systems to some extent. To set a specific file
system, you can change ``pyfakefs.FakeFilesystem.os`` to one of
@@ -780,11 +906,11 @@ attributes, which can also be set separately if needed:
- ``is_windows_fs`` - if ``True`` a Windows file system (NTFS) is assumed
- ``is_macos`` - if ``True`` and ``is_windows_fs`` is ``False``, the
- standard MacOS file system (HFS+) is assumed
+ standard macOS file system (HFS+) is assumed
- if ``is_windows_fs`` and ``is_macos`` are ``False``, a Linux file system
(something like ext3) is assumed
- ``is_case_sensitive`` is set to ``True`` under Linux and to ``False``
- under Windows and MacOS by default - you can change it to change the
+ under Windows and macOS by default - you can change it to change the
respective behavior
- ``path_separator`` is set to ``\`` under Windows and to ``/`` under Posix,
``alternative_path_separator`` is set to ``/`` under Windows and to
@@ -796,144 +922,39 @@ The following test works both under Windows and Linux:
from pyfakefs.fake_filesystem import OSType
+
def test_windows_paths(fs):
fs.os = OSType.WINDOWS
- assert r"C:\foo\bar" == os.path.join('C:\\', 'foo', 'bar'))
+ assert r"C:\foo\bar" == os.path.join("C:\\", "foo", "bar")
assert os.path.splitdrive(r"C:\foo\bar") == ("C:", r"\foo\bar")
assert os.path.ismount("C:")
-Troubleshooting
----------------
-
-Modules not working with pyfakefs
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Modules may not work with ``pyfakefs`` for several reasons. ``pyfakefs``
-works by patching some file system related modules and functions, specifically:
-
-- most file system related functions in the ``os`` and ``os.path`` modules
-- the ``pathlib`` module
-- the build-in ``open`` function and ``io.open``
-- ``shutil.disk_usage``
-
-Other file system related modules work with ``pyfakefs``, because they use
-exclusively these patched functions, specifically ``shutil`` (except for
-``disk_usage``), ``tempfile``, ``glob`` and ``zipfile``.
-
-A module may not work with ``pyfakefs`` because of one of the following
-reasons:
-
-- It uses a file system related function of the mentioned modules that is
- not or not correctly patched. Mostly these are functions that are seldom
- used, but may be used in Python libraries (this has happened for example
- with a changed implementation of ``shutil`` in Python 3.7). Generally,
- these shall be handled in issues and we are happy to fix them.
-- It uses file system related functions in a way that will not be patched
- automatically. This is the case for functions that are executed while
- reading a module. This case and a possibility to make them work is
- documented above under ``modules_to_reload``.
-- It uses OS specific file system functions not contained in the Python
- libraries. These will not work out of the box, and we generally will not
- support them in ``pyfakefs``. If these functions are used in isolated
- functions or classes, they may be patched by using the ``modules_to_patch``
- parameter (see the example for file locks in Django above), or by using
- ``unittest.patch`` if you don't need to simulate the functions. We
- added some of these patches to ``pyfakefs``, so that they are applied
- automatically (currently done for some ``pandas`` and ``Django``
- functionality).
-- It uses C libraries to access the file system. There is no way no make
- such a module work with ``pyfakefs``--if you want to use it, you
- have to patch the whole module. In some cases, a library implemented in
- Python with a similar interface already exists. An example is ``lxml``,
- which can be substituted with ``ElementTree`` in most cases for testing.
-
-A list of Python modules that are known to not work correctly with
-``pyfakefs`` will be collected here:
-
-- `multiprocessing`_ has several issues (related to points 1 and 3 above).
- Currently there are no plans to fix this, but this may change in case of
- sufficient demand.
-- `subprocess`_ has very similar problems and cannot be used with
- ``pyfakefs`` to start a process. ``subprocess`` can either be mocked, if
- the process is not needed for the test, or patching can be paused to start
- a process if needed, and resumed afterwards
- (see `this issue <https://github.com/jmcgeheeiv/pyfakefs/issues/447>`__).
-- Modules that rely on ``subprocess`` or ``multiprocessing`` to work
- correctly, e.g. need to start other executables. Examples that have shown
- this problem include `GitPython`_ and `plumbum`_.
-- the `Pillow`_ image library does not work with pyfakefs at least if writing
- JPEG files (see `this issue <https://github.com/jmcgeheeiv/pyfakefs/issues/529>`__)
-- `pandas`_ (the Python data analysis library) uses its own internal file
- system access written in C. Thus much of ``pandas`` will not work with
- ``pyfakefs``. Having said that, ``pyfakefs`` patches ``pandas`` so that many
- of the ``read_xxx`` functions, including ``read_csv`` and ``read_excel``,
- as well as some writer functions, do work with the fake file system. If
- you use only these functions, ``pyfakefs`` will work with ``pandas``.
-
-If you are not sure if a module can be handled, or how to do it, you can
-always write a new issue, of course!
-
-Pyfakefs behaves differently than the real filesystem
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-There are basically two kinds of deviations from the actual behavior:
-
-- unwanted deviations that we didn't notice--if you find any of these, please
- write an issue and will try to fix it
-- behavior that depends on different OS versions and editions--as mentioned
- in :ref:`limitations`, ``pyfakefs`` uses the TravisCI systems as reference
- system and will not replicate all system-specific behavior
-
-OS temporary directories
-~~~~~~~~~~~~~~~~~~~~~~~~
+Set file as inaccessible under Windows
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Normally, if you try to set a file or directory as inaccessible using ``chmod`` under
+Windows, the value you provide is masked by a value that always ensures that no read
+permissions for any user are removed. In reality, there is the possibility to make
+a file or directory unreadable using the Windows ACL API, which is not directly
+supported in the Python filesystem API. To make this possible to test, there is the
+possibility to use the ``force_unix_mode`` argument to ``FakeFilesystem.chmod``:
-Tests relying on a completely empty file system on test start will fail.
-As ``pyfakefs`` does not fake the ``tempfile`` module (as described above),
-a temporary directory is required to ensure ``tempfile`` works correctly,
-e.g., that ``tempfile.gettempdir()`` will return a valid value. This
-means that any newly created fake file system will always have either a
-directory named ``/tmp`` when running on Linux or Unix systems,
-``/var/folders/<hash>/T`` when running on MacOs, or
-``C:\Users\<user>\AppData\Local\Temp`` on Windows.
-
-User rights
-~~~~~~~~~~~
-
-If you run ``pyfakefs`` tests as root (this happens by default if run in a
-docker container), ``pyfakefs`` also behaves as a root user, for example can
-write to write-protected files. This may not be the expected behavior, and
-can be changed.
-``Pyfakefs`` has a rudimentary concept of user rights, which differentiates
-between root user (with the user id 0) and any other user. By default,
-``pyfakefs`` assumes the user id of the current user, but you can change
-that using ``fake_filesystem.set_uid()`` in your setup. This allows to run
-tests as non-root user in a root user environment and vice verse.
-Another possibility to run tests as non-root user in a root user environment
-is the convenience argument :ref:`allow_root_user`.
-
-.. _usage_with_mock_open:
-
-Pyfakefs and mock_open
-~~~~~~~~~~~~~~~~~~~~~~
-If you patch ``open`` using ``mock_open`` before the initialization of
-``pyfakefs``, it will not work properly, because the ``pyfakefs``
-initialization relies on ``open`` working correctly.
-Generally, you should not need ``mock_open`` if using ``pyfakefs``, because you
-always can create the files with the needed content using ``create_file``.
-This is true for patching any filesystem functions - avoid patching them
-while working with ``pyfakefs``.
-If you still want to use ``mock_open``, make sure it is only used while
-patching is in progress. For example, if you are using ``pytest`` with the
-``mocker`` fixture used to patch ``open``, make sure that the ``fs`` fixture is
-passed before the ``mocker`` fixture to ensure this.
-
-.. _`example.py`: https://github.com/jmcgeheeiv/pyfakefs/blob/master/pyfakefs/tests/example.py
-.. _`example_test.py`: https://github.com/jmcgeheeiv/pyfakefs/blob/master/pyfakefs/tests/example_test.py
+.. code:: python
+
+ def test_is_file_for_unreadable_dir_windows(fs):
+ fs.os = OSType.WINDOWS
+ path = pathlib.Path("/foo/bar")
+ fs.create_file(path)
+ # normal chmod does not really set the mode to 0
+ self.fs.chmod("/foo", 0o000)
+ assert path.is_file()
+ # but it does in forced UNIX mode
+ fs.chmod("/foo", 0o000, force_unix_mode=True)
+ with pytest.raises(PermissionError):
+ path.is_file()
+
+
+.. _`example.py`: https://github.com/pytest-dev/pyfakefs/blob/main/pyfakefs/tests/example.py
+.. _`example_test.py`: https://github.com/pytest-dev/pyfakefs/blob/main/pyfakefs/tests/example_test.py
.. _`pytest`: https://doc.pytest.org
.. _`nose`: https://docs.nose2.io/en/latest/
-.. _`all Patcher arguments`: https://jmcgeheeiv.github.io/pyfakefs/master/modules.html#pyfakefs.fake_filesystem_unittest.Patcher
-.. _`multiprocessing`: https://docs.python.org/3/library/multiprocessing.html
-.. _`subprocess`: https://docs.python.org/3/library/subprocess.html
-.. _`GitPython`: https://pypi.org/project/GitPython/
-.. _`plumbum`: https://pypi.org/project/plumbum/
-.. _`Pillow`: https://pypi.org/project/Pillow/
-.. _`pandas`: https://pypi.org/project/pandas/ \ No newline at end of file
+.. _`all Patcher arguments`: https://pytest-pyfakefs.readthedocs.io/en/latest/modules.html#pyfakefs.fake_filesystem_unittest.Patcher
diff --git a/extra_requirements.txt b/extra_requirements.txt
index eeaaad2..6c69b9c 100644
--- a/extra_requirements.txt
+++ b/extra_requirements.txt
@@ -13,9 +13,7 @@ scandir>=1.8
# pandas + xlrd are used to test pandas-specific patches to allow
# pyfakefs to work with pandas
# we use the latest version to see any problems with new versions
-pandas==1.1.5; python_version <= '3.6'
-pandas==1.3.5; python_version == '3.7'
-pandas==1.4.1; python_version > '3.7'
-xlrd==1.2.0; python_version <= '3.6'
-xlrd==2.0.1; python_version > '3.6'
-openpyxl==3.0.9
+pandas==1.3.5; python_version == '3.7' # pyup: ignore
+pandas==2.0.3; python_version > '3.7'
+xlrd==2.0.1
+openpyxl==3.1.2
diff --git a/pyfakefs/__init__.py b/pyfakefs/__init__.py
index 3a8d6d5..e8b4e1e 100755
--- a/pyfakefs/__init__.py
+++ b/pyfakefs/__init__.py
@@ -1 +1 @@
-from ._version import __version__ # noqa: F401
+from pyfakefs._version import __version__ # noqa: F401
diff --git a/pyfakefs/_version.py b/pyfakefs/_version.py
index 37846a0..bdb37fc 100644
--- a/pyfakefs/_version.py
+++ b/pyfakefs/_version.py
@@ -1 +1 @@
-__version__ = '4.6.dev0'
+__version__ = "5.3.dev0"
diff --git a/pyfakefs/deprecator.py b/pyfakefs/deprecator.py
deleted file mode 100644
index 99d0ae6..0000000
--- a/pyfakefs/deprecator.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Utilities for handling deprecated functions."""
-
-import functools
-import warnings
-
-
-class Deprecator(object):
- """Decorator class for adding deprecated functions.
-
- Warnings are switched on by default.
- To disable deprecation warnings, use:
-
- >>> from pyfakefs.deprecator import Deprecator
- >>>
- >>> Deprecator.show_warnings = False
- """
-
- show_warnings = True
-
- def __init__(self, use_instead=None, func_name=None):
- self.use_instead = use_instead
- self.func_name = func_name
-
- def __call__(self, func):
- """Decorator to mark functions as deprecated. Emit warning
- when the function is used."""
-
- @functools.wraps(func)
- def _new_func(*args, **kwargs):
- if self.show_warnings:
- with warnings.catch_warnings():
- warnings.simplefilter('always', DeprecationWarning)
- message = ''
- if self.use_instead is not None:
- message = 'Use {} instead.'.format(self.use_instead)
- warnings.warn('Call to deprecated function {}. {}'.format(
- self.func_name or func.__name__, message),
- category=DeprecationWarning, stacklevel=2)
- return func(*args, **kwargs)
-
- return _new_func
-
- @staticmethod
- def add(clss, func, deprecated_name):
- """Add the deprecated version of a member function to the given class.
- Gives a deprecation warning on usage.
-
- Args:
- clss: the class where the deprecated function is to be added
- func: the actual function that is called by the deprecated version
- deprecated_name: the deprecated name of the function
- """
-
- @Deprecator(func.__name__, deprecated_name)
- def _old_function(*args, **kwargs):
- return func(*args, **kwargs)
-
- setattr(clss, deprecated_name, _old_function)
diff --git a/pyfakefs/extra_packages.py b/pyfakefs/extra_packages.py
index d45c854..23e0814 100644
--- a/pyfakefs/extra_packages.py
+++ b/pyfakefs/extra_packages.py
@@ -11,7 +11,7 @@
# limitations under the License.
"""Imports external packages that replace or emulate internal packages.
-If the external module is not present, the build-in module is imported.
+If the external module is not present, the built-in module is imported.
"""
try:
diff --git a/pyfakefs/fake_file.py b/pyfakefs/fake_file.py
new file mode 100644
index 0000000..5bc3119
--- /dev/null
+++ b/pyfakefs/fake_file.py
@@ -0,0 +1,1316 @@
+# Copyright 2009 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Fake implementations for different file objects.
+"""
+import errno
+import io
+import locale
+import os
+import sys
+from stat import (
+ S_IFREG,
+ S_IFDIR,
+)
+from types import TracebackType
+from typing import (
+ List,
+ Optional,
+ Callable,
+ Union,
+ Any,
+ Dict,
+ cast,
+ AnyStr,
+ NoReturn,
+ Iterator,
+ TextIO,
+ Type,
+ TYPE_CHECKING,
+)
+
+from pyfakefs import helpers
+from pyfakefs.helpers import (
+ FakeStatResult,
+ BinaryBufferIO,
+ TextBufferIO,
+ is_int_type,
+ is_unicode_string,
+ to_string,
+ matching_string,
+ real_encoding,
+ AnyPath,
+ AnyString,
+)
+
+if TYPE_CHECKING:
+ from pyfakefs.fake_filesystem import FakeFilesystem
+
+AnyFileWrapper = Union[
+ "FakeFileWrapper",
+ "FakeDirWrapper",
+ "StandardStreamWrapper",
+ "FakePipeWrapper",
+]
+AnyFile = Union["FakeFile", "FakeDirectory"]
+
+
+class FakeLargeFileIoException(Exception):
+ """Exception thrown on unsupported operations for fake large files.
+ Fake large files have a size with no real content.
+ """
+
+ def __init__(self, file_path: str) -> None:
+ super(FakeLargeFileIoException, self).__init__(
+ "Read and write operations not supported for "
+ "fake large file: %s" % file_path
+ )
+
+
+class FakeFile:
+ """Provides the appearance of a real file.
+
+ Attributes currently faked out:
+ * `st_mode`: user-specified, otherwise S_IFREG
+ * `st_ctime`: the time.time() timestamp of the file change time (updated
+ each time a file's attributes is modified).
+ * `st_atime`: the time.time() timestamp when the file was last accessed.
+ * `st_mtime`: the time.time() timestamp when the file was last modified.
+ * `st_size`: the size of the file
+ * `st_nlink`: the number of hard links to the file
+ * `st_ino`: the inode number - a unique number identifying the file
+ * `st_dev`: a unique number identifying the (fake) file system device
+ the file belongs to
+ * `st_uid`: always set to USER_ID, which can be changed globally using
+ `set_uid`
+ * `st_gid`: always set to GROUP_ID, which can be changed globally using
+ `set_gid`
+
+ .. note:: The resolution for `st_ctime`, `st_mtime` and `st_atime` in the
+ real file system depends on the used file system (for example it is
+ only 1s for HFS+ and older Linux file systems, but much higher for
+ ext4 and NTFS). This is currently ignored by pyfakefs, which uses
+ the resolution of `time.time()`.
+
+ Under Windows, `st_atime` is not updated for performance reasons by
+ default. pyfakefs never updates `st_atime` under Windows, assuming
+ the default setting.
+ """
+
+ stat_types = (
+ "st_mode",
+ "st_ino",
+ "st_dev",
+ "st_nlink",
+ "st_uid",
+ "st_gid",
+ "st_size",
+ "st_atime",
+ "st_mtime",
+ "st_ctime",
+ "st_atime_ns",
+ "st_mtime_ns",
+ "st_ctime_ns",
+ )
+
+ def __init__(
+ self,
+ name: AnyStr,
+ st_mode: int = S_IFREG | helpers.PERM_DEF_FILE,
+ contents: Optional[AnyStr] = None,
+ filesystem: Optional["FakeFilesystem"] = None,
+ encoding: Optional[str] = None,
+ errors: Optional[str] = None,
+ side_effect: Optional[Callable[["FakeFile"], None]] = None,
+ ):
+ """
+ Args:
+ name: Name of the file/directory, without parent path information
+ st_mode: The stat.S_IF* constant representing the file type (i.e.
+ stat.S_IFREG, stat.S_IFDIR), and the file permissions.
+ If no file type is set (e.g. permission flags only), a
+ regular file type is assumed.
+ contents: The contents of the filesystem object; should be a string
+ or byte object for regular files, and a dict of other
+ FakeFile or FakeDirectory objects with the file names as
+ keys for FakeDirectory objects
+ filesystem: The fake filesystem where the file is created.
+ encoding: If contents is a unicode string, the encoding used
+ for serialization.
+ errors: The error mode used for encoding/decoding errors.
+ side_effect: function handle that is executed when file is written,
+ must accept the file object as an argument.
+ """
+ # to be backwards compatible regarding argument order, we raise on None
+ if filesystem is None:
+ raise ValueError("filesystem shall not be None")
+ self.filesystem: "FakeFilesystem" = filesystem
+ self._side_effect: Optional[Callable] = side_effect
+ self.name: AnyStr = name # type: ignore[assignment]
+ self.stat_result = FakeStatResult(
+ filesystem.is_windows_fs,
+ helpers.get_uid(),
+ helpers.get_gid(),
+ helpers.now(),
+ )
+ if st_mode >> 12 == 0:
+ st_mode |= S_IFREG
+ self.stat_result.st_mode = st_mode
+ self.st_size: int = 0
+ self.encoding: Optional[str] = real_encoding(encoding)
+ self.errors: str = errors or "strict"
+ self._byte_contents: Optional[bytes] = self._encode_contents(contents)
+ self.stat_result.st_size = (
+ len(self._byte_contents) if self._byte_contents is not None else 0
+ )
+ self.epoch: int = 0
+ self.parent_dir: Optional[FakeDirectory] = None
+ # Linux specific: extended file system attributes
+ self.xattr: Dict = {}
+ self.opened_as: AnyString = ""
+
+ @property
+ def byte_contents(self) -> Optional[bytes]:
+ """Return the contents as raw byte array."""
+ return self._byte_contents
+
+ @property
+ def contents(self) -> Optional[str]:
+ """Return the contents as string with the original encoding."""
+ if isinstance(self.byte_contents, bytes):
+ return self.byte_contents.decode(
+ self.encoding or locale.getpreferredencoding(False),
+ errors=self.errors,
+ )
+ return None
+
+ @property
+ def st_ctime(self) -> float:
+ """Return the creation time of the fake file."""
+ return self.stat_result.st_ctime
+
+ @st_ctime.setter
+ def st_ctime(self, val: float) -> None:
+ """Set the creation time of the fake file."""
+ self.stat_result.st_ctime = val
+
+ @property
+ def st_atime(self) -> float:
+ """Return the access time of the fake file."""
+ return self.stat_result.st_atime
+
+ @st_atime.setter
+ def st_atime(self, val: float) -> None:
+ """Set the access time of the fake file."""
+ self.stat_result.st_atime = val
+
+ @property
+ def st_mtime(self) -> float:
+ """Return the modification time of the fake file."""
+ return self.stat_result.st_mtime
+
+ @st_mtime.setter
+ def st_mtime(self, val: float) -> None:
+ """Set the modification time of the fake file."""
+ self.stat_result.st_mtime = val
+
+ def set_large_file_size(self, st_size: int) -> None:
+ """Sets the self.st_size attribute and replaces self.content with None.
+
+ Provided specifically to simulate very large files without regards
+ to their content (which wouldn't fit in memory).
+ Note that read/write operations with such a file raise
+ :py:class:`FakeLargeFileIoException`.
+
+ Args:
+ st_size: (int) The desired file size
+
+ Raises:
+ OSError: if the st_size is not a non-negative integer,
+ or if st_size exceeds the available file system space
+ """
+ self._check_positive_int(st_size)
+ if self.st_size:
+ self.size = 0
+ if self.filesystem:
+ self.filesystem.change_disk_usage(st_size, self.name, self.st_dev)
+ self.st_size = st_size
+ self._byte_contents = None
+
+ def _check_positive_int(self, size: int) -> None:
+ # the size should be an positive integer value
+ if not is_int_type(size) or size < 0:
+ self.filesystem.raise_os_error(errno.ENOSPC, self.name)
+
+ def is_large_file(self) -> bool:
+ """Return `True` if this file was initialized with size
+ but no contents.
+ """
+ return self._byte_contents is None
+
+ def _encode_contents(self, contents: Union[str, bytes, None]) -> Optional[bytes]:
+ if is_unicode_string(contents):
+ contents = bytes(
+ cast(str, contents),
+ self.encoding or locale.getpreferredencoding(False),
+ self.errors,
+ )
+ return cast(bytes, contents)
+
+ def set_initial_contents(self, contents: AnyStr) -> bool:
+ """Sets the file contents and size.
+ Called internally after initial file creation.
+
+ Args:
+ contents: string, new content of file.
+
+ Returns:
+ True if the contents have been changed.
+
+ Raises:
+ OSError: if the st_size is not a non-negative integer,
+ or if st_size exceeds the available file system space
+ """
+ byte_contents = self._encode_contents(contents)
+ changed = self._byte_contents != byte_contents
+ st_size = len(byte_contents) if byte_contents else 0
+
+ current_size = self.st_size or 0
+ self.filesystem.change_disk_usage(
+ st_size - current_size, self.name, self.st_dev
+ )
+ self._byte_contents = byte_contents
+ self.st_size = st_size
+ self.epoch += 1
+ return changed
+
+ def set_contents(self, contents: AnyStr, encoding: Optional[str] = None) -> bool:
+ """Sets the file contents and size and increases the modification time.
+ Also executes the side_effects if available.
+
+ Args:
+ contents: (str, bytes) new content of file.
+ encoding: (str) the encoding to be used for writing the contents
+ if they are a unicode string.
+ If not given, the locale preferred encoding is used.
+
+ Returns:
+ True if the contents have been changed.
+
+ Raises:
+ OSError: if `st_size` is not a non-negative integer,
+ or if it exceeds the available file system space.
+ """
+ self.encoding = real_encoding(encoding)
+ changed = self.set_initial_contents(contents)
+ if self._side_effect is not None:
+ self._side_effect(self)
+ return changed
+
+ @property
+ def size(self) -> int:
+ """Return the size in bytes of the file contents."""
+ return self.st_size
+
+ @size.setter
+ def size(self, st_size: int) -> None:
+ """Resizes file content, padding with nulls if new size exceeds the
+ old size.
+
+ Args:
+ st_size: The desired size for the file.
+
+ Raises:
+ OSError: if the st_size arg is not a non-negative integer
+ or if st_size exceeds the available file system space
+ """
+
+ self._check_positive_int(st_size)
+ current_size = self.st_size or 0
+ self.filesystem.change_disk_usage(
+ st_size - current_size, self.name, self.st_dev
+ )
+ if self._byte_contents:
+ if st_size < current_size:
+ self._byte_contents = self._byte_contents[:st_size]
+ else:
+ self._byte_contents += b"\0" * (st_size - current_size)
+ self.st_size = st_size
+ self.epoch += 1
+
+ @property
+ def path(self) -> AnyStr:
+ """Return the full path of the current object."""
+ names: List[AnyStr] = [] # pytype: disable=invalid-annotation
+ obj: Optional[FakeFile] = self
+ while obj:
+ names.insert(0, matching_string(self.name, obj.name)) # type: ignore
+ obj = obj.parent_dir
+ sep = self.filesystem.get_path_separator(names[0])
+ if names[0] == sep:
+ names.pop(0)
+ dir_path = sep.join(names)
+ drive = self.filesystem.splitdrive(dir_path)[0]
+ # if a Windows path already starts with a drive or UNC path,
+ # no extra separator is needed
+ if not drive:
+ dir_path = sep + dir_path
+ else:
+ dir_path = sep.join(names)
+ return self.filesystem.absnormpath(dir_path)
+
+ if sys.version_info >= (3, 12):
+
+ @property
+ def is_junction(self) -> bool:
+ return self.filesystem.isjunction(self.path)
+
+ def __getattr__(self, item: str) -> Any:
+ """Forward some properties to stat_result."""
+ if item in self.stat_types:
+ return getattr(self.stat_result, item)
+ return super().__getattribute__(item)
+
+ def __setattr__(self, key: str, value: Any) -> None:
+ """Forward some properties to stat_result."""
+ if key in self.stat_types:
+ return setattr(self.stat_result, key, value)
+ return super().__setattr__(key, value)
+
+ def __str__(self) -> str:
+ return "%r(%o)" % (self.name, self.st_mode)
+
+
+class FakeNullFile(FakeFile):
+ def __init__(self, filesystem: "FakeFilesystem") -> None:
+ devnull = "nul" if filesystem.is_windows_fs else "/dev/null"
+ super(FakeNullFile, self).__init__(devnull, filesystem=filesystem, contents="")
+
+ @property
+ def byte_contents(self) -> bytes:
+ return b""
+
+ def set_initial_contents(self, contents: AnyStr) -> bool:
+ return False
+
+
+class FakeFileFromRealFile(FakeFile):
+ """Represents a fake file copied from the real file system.
+
+ The contents of the file are read on demand only.
+ """
+
+ def __init__(
+ self,
+ file_path: str,
+ filesystem: "FakeFilesystem",
+ side_effect: Optional[Callable] = None,
+ ) -> None:
+ """
+ Args:
+ file_path: Path to the existing file.
+ filesystem: The fake filesystem where the file is created.
+
+ Raises:
+ OSError: if the file does not exist in the real file system.
+ OSError: if the file already exists in the fake file system.
+ """
+ super().__init__(
+ name=os.path.basename(file_path),
+ filesystem=filesystem,
+ side_effect=side_effect,
+ )
+ self.contents_read = False
+
+ @property
+ def byte_contents(self) -> Optional[bytes]:
+ if not self.contents_read:
+ self.contents_read = True
+ with io.open(self.file_path, "rb") as f:
+ self._byte_contents = f.read()
+ # On MacOS and BSD, the above io.open() updates atime on the real file
+ self.st_atime = os.stat(self.file_path).st_atime
+ return self._byte_contents
+
+ def set_contents(self, contents, encoding=None):
+ self.contents_read = True
+ super(FakeFileFromRealFile, self).set_contents(contents, encoding)
+
+ def is_large_file(self):
+ """The contents are never faked."""
+ return False
+
+
+class FakeDirectory(FakeFile):
+ """Provides the appearance of a real directory."""
+
+ def __init__(
+ self,
+ name: str,
+ perm_bits: int = helpers.PERM_DEF,
+ filesystem: Optional["FakeFilesystem"] = None,
+ ):
+ """
+ Args:
+ name: name of the file/directory, without parent path information
+ perm_bits: permission bits. defaults to 0o777.
+ filesystem: if set, the fake filesystem where the directory
+ is created
+ """
+ FakeFile.__init__(self, name, S_IFDIR | perm_bits, "", filesystem=filesystem)
+ # directories have the link count of contained entries,
+ # including '.' and '..'
+ self.st_nlink += 1
+ self._entries: Dict[str, AnyFile] = {}
+
+ def set_contents(self, contents: AnyStr, encoding: Optional[str] = None) -> bool:
+ raise self.filesystem.raise_os_error(errno.EISDIR, self.path)
+
+ @property
+ def entries(self) -> Dict[str, FakeFile]:
+ """Return the list of contained directory entries."""
+ return self._entries
+
+ @property
+ def ordered_dirs(self) -> List[str]:
+ """Return the list of contained directory entry names ordered by
+ creation order.
+ """
+ return [
+ item[0]
+ for item in sorted(self._entries.items(), key=lambda entry: entry[1].st_ino)
+ ]
+
+ def add_entry(self, path_object: FakeFile) -> None:
+ """Adds a child FakeFile to this directory.
+
+ Args:
+ path_object: FakeFile instance to add as a child of this directory.
+
+ Raises:
+ OSError: if the directory has no write permission (Posix only)
+ OSError: if the file or directory to be added already exists
+ """
+ if (
+ not helpers.is_root()
+ and not self.st_mode & helpers.PERM_WRITE
+ and not self.filesystem.is_windows_fs
+ ):
+ raise OSError(errno.EACCES, "Permission Denied", self.path)
+
+ path_object_name: str = to_string(path_object.name)
+ if path_object_name in self.entries:
+ self.filesystem.raise_os_error(errno.EEXIST, self.path)
+
+ self._entries[path_object_name] = path_object
+ path_object.parent_dir = self
+ if path_object.st_ino is None:
+ self.filesystem.last_ino += 1
+ path_object.st_ino = self.filesystem.last_ino
+ self.st_nlink += 1
+ path_object.st_nlink += 1
+ path_object.st_dev = self.st_dev
+ if path_object.st_nlink == 1:
+ self.filesystem.change_disk_usage(
+ path_object.size, path_object.name, self.st_dev
+ )
+
+ def get_entry(self, pathname_name: str) -> AnyFile:
+ """Retrieves the specified child file or directory entry.
+
+ Args:
+ pathname_name: The basename of the child object to retrieve.
+
+ Returns:
+ The fake file or directory object.
+
+ Raises:
+ KeyError: if no child exists by the specified name.
+ """
+ pathname_name = self._normalized_entryname(pathname_name)
+ return self.entries[to_string(pathname_name)]
+
+ def _normalized_entryname(self, pathname_name: str) -> str:
+ if not self.filesystem.is_case_sensitive:
+ matching_names = [
+ name for name in self.entries if name.lower() == pathname_name.lower()
+ ]
+ if matching_names:
+ pathname_name = matching_names[0]
+ return pathname_name
+
+ def remove_entry(self, pathname_name: str, recursive: bool = True) -> None:
+ """Removes the specified child file or directory.
+
+ Args:
+ pathname_name: Basename of the child object to remove.
+ recursive: If True (default), the entries in contained directories
+ are deleted first. Used to propagate removal errors
+ (e.g. permission problems) from contained entries.
+
+ Raises:
+ KeyError: if no child exists by the specified name.
+ OSError: if user lacks permission to delete the file,
+ or (Windows only) the file is open.
+ """
+ pathname_name = self._normalized_entryname(pathname_name)
+ entry = self.get_entry(pathname_name)
+ if self.filesystem.is_windows_fs:
+ if entry.st_mode & helpers.PERM_WRITE == 0:
+ self.filesystem.raise_os_error(errno.EACCES, pathname_name)
+ if self.filesystem.has_open_file(entry):
+ self.filesystem.raise_os_error(errno.EACCES, pathname_name)
+ else:
+ if not helpers.is_root() and (
+ self.st_mode & (helpers.PERM_WRITE | helpers.PERM_EXE)
+ != helpers.PERM_WRITE | helpers.PERM_EXE
+ ):
+ self.filesystem.raise_os_error(errno.EACCES, pathname_name)
+
+ if recursive and isinstance(entry, FakeDirectory):
+ while entry.entries:
+ entry.remove_entry(list(entry.entries)[0])
+ elif entry.st_nlink == 1:
+ self.filesystem.change_disk_usage(-entry.size, pathname_name, entry.st_dev)
+
+ self.st_nlink -= 1
+ entry.st_nlink -= 1
+ assert entry.st_nlink >= 0
+
+ del self.entries[to_string(pathname_name)]
+
+ @property
+ def size(self) -> int:
+ """Return the total size of all files contained
+ in this directory tree.
+ """
+ return sum([item[1].size for item in self.entries.items()])
+
+ @size.setter
+ def size(self, st_size: int) -> None:
+ """Setting the size is an error for a directory."""
+ raise self.filesystem.raise_os_error(errno.EISDIR, self.path)
+
+ def has_parent_object(self, dir_object: "FakeDirectory") -> bool:
+ """Return `True` if dir_object is a direct or indirect parent
+ directory, or if both are the same object."""
+ obj: Optional[FakeDirectory] = self
+ while obj:
+ if obj == dir_object:
+ return True
+ obj = obj.parent_dir
+ return False
+
+ def __str__(self) -> str:
+ description = super(FakeDirectory, self).__str__() + ":\n"
+ for item in self.entries:
+ item_desc = self.entries[item].__str__()
+ for line in item_desc.split("\n"):
+ if line:
+ description = description + " " + line + "\n"
+ return description
+
+
+class FakeDirectoryFromRealDirectory(FakeDirectory):
+ """Represents a fake directory copied from the real file system.
+
+ The contents of the directory are read on demand only.
+ """
+
+ def __init__(
+ self,
+ source_path: AnyPath,
+ filesystem: "FakeFilesystem",
+ read_only: bool,
+ target_path: Optional[AnyPath] = None,
+ ):
+ """
+ Args:
+ source_path: Full directory path.
+ filesystem: The fake filesystem where the directory is created.
+ read_only: If set, all files under the directory are treated
+ as read-only, e.g. a write access raises an exception;
+ otherwise, writing to the files changes the fake files
+ only as usually.
+ target_path: If given, the target path of the directory,
+ otherwise the target is the same as `source_path`.
+
+ Raises:
+ OSError: if the directory does not exist in the real file system
+ """
+ target_path = target_path or source_path
+ real_stat = os.stat(source_path)
+ super(FakeDirectoryFromRealDirectory, self).__init__(
+ name=to_string(os.path.split(target_path)[1]),
+ perm_bits=real_stat.st_mode,
+ filesystem=filesystem,
+ )
+
+ self.st_ctime = real_stat.st_ctime
+ self.st_atime = real_stat.st_atime
+ self.st_mtime = real_stat.st_mtime
+ self.st_gid = real_stat.st_gid
+ self.st_uid = real_stat.st_uid
+ self.source_path = source_path # type: ignore
+ self.read_only = read_only
+ self.contents_read = False
+
+ @property
+ def entries(self) -> Dict[str, FakeFile]:
+ """Return the list of contained directory entries, loading them
+ if not already loaded."""
+ if not self.contents_read:
+ self.contents_read = True
+ base = self.path
+ for entry in os.listdir(self.source_path):
+ source_path = os.path.join(self.source_path, entry)
+ target_path = os.path.join(base, entry) # type: ignore
+ if os.path.islink(source_path):
+ self.filesystem.add_real_symlink(source_path, target_path)
+ elif os.path.isdir(source_path):
+ self.filesystem.add_real_directory(
+ source_path, self.read_only, target_path=target_path
+ )
+ else:
+ self.filesystem.add_real_file(
+ source_path, self.read_only, target_path=target_path
+ )
+ return self._entries
+
+ @property
+ def size(self) -> int:
+ # we cannot get the size until the contents are loaded
+ if not self.contents_read:
+ return 0
+ return super(FakeDirectoryFromRealDirectory, self).size
+
+ @size.setter
+ def size(self, st_size: int) -> None:
+ raise self.filesystem.raise_os_error(errno.EISDIR, self.path)
+
+
+class FakeFileWrapper:
+ """Wrapper for a stream object for use by a FakeFile object.
+
+ If the wrapper has any data written to it, it will propagate to
+ the FakeFile object on close() or flush().
+ """
+
+ def __init__(
+ self,
+ file_object: FakeFile,
+ file_path: AnyStr,
+ update: bool,
+ read: bool,
+ append: bool,
+ delete_on_close: bool,
+ filesystem: "FakeFilesystem",
+ newline: Optional[str],
+ binary: bool,
+ closefd: bool,
+ encoding: Optional[str],
+ errors: Optional[str],
+ buffering: int,
+ raw_io: bool,
+ is_stream: bool = False,
+ ):
+ self.file_object = file_object
+ self.file_path = file_path # type: ignore[var-annotated]
+ self._append = append
+ self._read = read
+ self.allow_update = update
+ self._closefd = closefd
+ self._file_epoch = file_object.epoch
+ self.raw_io = raw_io
+ self._binary = binary
+ self.is_stream = is_stream
+ self._changed = False
+ self._buffer_size = buffering
+ if self._buffer_size == 0 and not binary:
+ raise ValueError("can't have unbuffered text I/O")
+ # buffer_size is ignored in text mode
+ elif self._buffer_size == -1 or not binary:
+ self._buffer_size = io.DEFAULT_BUFFER_SIZE
+ self._use_line_buffer = not binary and buffering == 1
+
+ contents = file_object.byte_contents
+ self._encoding = encoding or locale.getpreferredencoding(False)
+ errors = errors or "strict"
+ self._io: Union[BinaryBufferIO, TextBufferIO] = (
+ BinaryBufferIO(contents)
+ if binary
+ else TextBufferIO(
+ contents, encoding=encoding, newline=newline, errors=errors
+ )
+ )
+ self._read_whence = 0
+ self._read_seek = 0
+ self._flush_pos = 0
+ if contents:
+ self._flush_pos = len(contents)
+ if update:
+ if not append:
+ self._io.seek(0)
+ else:
+ self._io.seek(self._flush_pos)
+ self._read_seek = self._io.tell()
+
+ if delete_on_close:
+ assert filesystem, "delete_on_close=True requires filesystem"
+ self._filesystem = filesystem
+ self.delete_on_close = delete_on_close
+ # override, don't modify FakeFile.name, as FakeFilesystem expects
+ # it to be the file name only, no directories.
+ self.name = file_object.opened_as
+ self.filedes: Optional[int] = None
+
+ def __enter__(self) -> "FakeFileWrapper":
+ """To support usage of this fake file with the 'with' statement."""
+ return self
+
+ def __exit__(
+ self,
+ exc_type: Optional[Type[BaseException]],
+ exc_val: Optional[BaseException],
+ exc_tb: Optional[TracebackType],
+ ) -> None:
+ """To support usage of this fake file with the 'with' statement."""
+ self.close()
+
+ def _raise(self, message: str) -> NoReturn:
+ if self.raw_io:
+ self._filesystem.raise_os_error(errno.EBADF, self.file_path)
+ raise io.UnsupportedOperation(message)
+
+ def get_object(self) -> FakeFile:
+ """Return the FakeFile object that is wrapped
+ by the current instance.
+ """
+ return self.file_object
+
+ def fileno(self) -> int:
+ """Return the file descriptor of the file object."""
+ if self.filedes is not None:
+ return self.filedes
+ raise OSError(errno.EBADF, "Invalid file descriptor")
+
+ def close(self) -> None:
+ """Close the file."""
+ # ignore closing a closed file
+ if not self._is_open():
+ return
+
+ # for raw io, all writes are flushed immediately
+ if self.allow_update and not self.raw_io:
+ self.flush()
+ if self._filesystem.is_windows_fs and self._changed:
+ self.file_object.st_mtime = helpers.now()
+
+ assert self.filedes is not None
+ if self._closefd:
+ self._filesystem._close_open_file(self.filedes)
+ else:
+ open_files = self._filesystem.open_files[self.filedes]
+ assert open_files is not None
+ open_files.remove(self)
+ if self.delete_on_close:
+ self._filesystem.remove_object(
+ self.get_object().path # type: ignore[arg-type]
+ )
+
+ @property
+ def closed(self) -> bool:
+ """Simulate the `closed` attribute on file."""
+ return not self._is_open()
+
+ def _try_flush(self, old_pos: int) -> None:
+ """Try to flush and reset the position if it fails."""
+ flush_pos = self._flush_pos
+ try:
+ self.flush()
+ except OSError:
+ # write failed - reset to previous position
+ self._io.seek(old_pos)
+ self._io.truncate()
+ self._flush_pos = flush_pos
+ raise
+
+ def flush(self) -> None:
+ """Flush file contents to 'disk'."""
+ self._check_open_file()
+ if self.allow_update and not self.is_stream:
+ contents = self._io.getvalue()
+ if self._append:
+ self._sync_io()
+ old_contents = self.file_object.byte_contents
+ assert old_contents is not None
+ contents = old_contents + contents[self._flush_pos :]
+ self._set_stream_contents(contents)
+ else:
+ self._io.flush()
+ changed = self.file_object.set_contents(contents, self._encoding)
+ self.update_flush_pos()
+ if changed:
+ if self._filesystem.is_windows_fs:
+ self._changed = True
+ else:
+ current_time = helpers.now()
+ self.file_object.st_ctime = current_time
+ self.file_object.st_mtime = current_time
+ self._file_epoch = self.file_object.epoch
+
+ if not self.is_stream:
+ self._flush_related_files()
+
+ def update_flush_pos(self) -> None:
+ self._flush_pos = self._io.tell()
+
+ def _flush_related_files(self) -> None:
+ for open_files in self._filesystem.open_files[3:]:
+ if open_files is not None:
+ for open_file in open_files:
+ if (
+ open_file is not self
+ and isinstance(open_file, FakeFileWrapper)
+ and self.file_object == open_file.file_object
+ and not open_file._append
+ ):
+ open_file._sync_io()
+
+ def seek(self, offset: int, whence: int = 0) -> None:
+ """Move read/write pointer in 'file'."""
+ self._check_open_file()
+ if not self._append:
+ self._io.seek(offset, whence)
+ else:
+ self._read_seek = offset
+ self._read_whence = whence
+ if not self.is_stream:
+ self.flush()
+
+ def tell(self) -> int:
+ """Return the file's current position.
+
+ Returns:
+ int, file's current position in bytes.
+ """
+ self._check_open_file()
+ if not self.is_stream:
+ self.flush()
+
+ if not self._append:
+ return self._io.tell()
+ if self._read_whence:
+ write_seek = self._io.tell()
+ self._io.seek(self._read_seek, self._read_whence)
+ self._read_seek = self._io.tell()
+ self._read_whence = 0
+ self._io.seek(write_seek)
+ return self._read_seek
+
+ def _sync_io(self) -> None:
+ """Update the stream with changes to the file object contents."""
+ if self._file_epoch == self.file_object.epoch:
+ return
+
+ contents = self.file_object.byte_contents
+ assert contents is not None
+ self._set_stream_contents(contents)
+ self._file_epoch = self.file_object.epoch
+
+ def _set_stream_contents(self, contents: bytes) -> None:
+ whence = self._io.tell()
+ self._io.seek(0)
+ self._io.truncate()
+ self._io.putvalue(contents)
+ if not self._append:
+ self._io.seek(whence)
+
+ def _read_wrappers(self, name: str) -> Callable:
+ """Wrap a stream attribute in a read wrapper.
+
+ Returns a read_wrapper which tracks our own read pointer since the
+ stream object has no concept of a different read and write pointer.
+
+ Args:
+ name: The name of the attribute to wrap. Should be a read call.
+
+ Returns:
+ The read_wrapper function.
+ """
+ io_attr = getattr(self._io, name)
+
+ def read_wrapper(*args, **kwargs):
+ """Wrap all read calls to the stream object.
+
+ We do this to track the read pointer separate from the write
+ pointer. Anything that wants to read from the stream object
+ while we're in append mode goes through this.
+
+ Args:
+ *args: pass through args
+ **kwargs: pass through kwargs
+ Returns:
+ Wrapped stream object method
+ """
+ self._io.seek(self._read_seek, self._read_whence)
+ ret_value = io_attr(*args, **kwargs)
+ self._read_seek = self._io.tell()
+ self._read_whence = 0
+ self._io.seek(0, 2)
+ return ret_value
+
+ return read_wrapper
+
+ def _other_wrapper(self, name: str) -> Callable:
+ """Wrap a stream attribute in an other_wrapper.
+
+ Args:
+ name: the name of the stream attribute to wrap.
+
+ Returns:
+ other_wrapper which is described below.
+ """
+ io_attr = getattr(self._io, name)
+
+ def other_wrapper(*args, **kwargs):
+ """Wrap all other calls to the stream Object.
+
+ We do this to track changes to the write pointer. Anything that
+ moves the write pointer in a file open for appending should move
+ the read pointer as well.
+
+ Args:
+ *args: Pass through args.
+ **kwargs: Pass through kwargs.
+
+ Returns:
+ Wrapped stream object method.
+ """
+ write_seek = self._io.tell()
+ ret_value = io_attr(*args, **kwargs)
+ if write_seek != self._io.tell():
+ self._read_seek = self._io.tell()
+ self._read_whence = 0
+
+ return ret_value
+
+ return other_wrapper
+
+ def _write_wrapper(self, name: str) -> Callable:
+ """Wrap a stream attribute in a write_wrapper.
+
+ Args:
+ name: the name of the stream attribute to wrap.
+
+ Returns:
+ write_wrapper which is described below.
+ """
+ io_attr = getattr(self._io, name)
+
+ def write_wrapper(*args, **kwargs):
+ """Wrap all other calls to the stream Object.
+
+ We do this to track changes to the write pointer. Anything that
+ moves the write pointer in a file open for appending should move
+ the read pointer as well.
+
+ Args:
+ *args: Pass through args.
+ **kwargs: Pass through kwargs.
+
+ Returns:
+ Wrapped stream object method.
+ """
+ old_pos = self._io.tell()
+ ret_value = io_attr(*args, **kwargs)
+ new_pos = self._io.tell()
+
+ # if the buffer size is exceeded, we flush
+ use_line_buf = self._use_line_buffer and "\n" in args[0]
+ if new_pos - self._flush_pos > self._buffer_size or use_line_buf:
+ flush_all = new_pos - old_pos > self._buffer_size or use_line_buf
+ # if the current write does not exceed the buffer size,
+ # we revert to the previous position and flush that,
+ # otherwise we flush all
+ if not flush_all:
+ self._io.seek(old_pos)
+ self._io.truncate()
+ self._try_flush(old_pos)
+ if not flush_all:
+ ret_value = io_attr(*args, **kwargs)
+ if self._append:
+ self._read_seek = self._io.tell()
+ self._read_whence = 0
+ return ret_value
+
+ return write_wrapper
+
+ def _adapt_size_for_related_files(self, size: int) -> None:
+ for open_files in self._filesystem.open_files[3:]:
+ if open_files is not None:
+ for open_file in open_files:
+ if (
+ open_file is not self
+ and isinstance(open_file, FakeFileWrapper)
+ and self.file_object == open_file.file_object
+ and cast(FakeFileWrapper, open_file)._append
+ ):
+ open_file._read_seek += size
+
+ def _truncate_wrapper(self) -> Callable:
+ """Wrap truncate() to allow flush after truncate.
+
+ Returns:
+ Wrapper which is described below.
+ """
+ io_attr = self._io.truncate
+
+ def truncate_wrapper(*args, **kwargs):
+ """Wrap truncate call to call flush after truncate."""
+ if self._append:
+ self._io.seek(self._read_seek, self._read_whence)
+ size = io_attr(*args, **kwargs)
+ self.flush()
+ if not self.is_stream:
+ self.file_object.size = size
+ buffer_size = len(self._io.getvalue())
+ if buffer_size < size:
+ self._io.seek(buffer_size)
+ self._io.putvalue(b"\0" * (size - buffer_size))
+ self.file_object.set_contents(self._io.getvalue(), self._encoding)
+ self._flush_pos = size
+ self._adapt_size_for_related_files(size - buffer_size)
+
+ self.flush()
+ return size
+
+ return truncate_wrapper
+
+ def size(self) -> int:
+ """Return the content size in bytes of the wrapped file."""
+ return self.file_object.st_size
+
+ def __getattr__(self, name: str) -> Any:
+ if self.file_object.is_large_file():
+ raise FakeLargeFileIoException(self.file_path)
+
+ reading = name.startswith("read") or name == "next"
+ truncate = name == "truncate"
+ writing = name.startswith("write") or truncate
+
+ if reading or writing:
+ self._check_open_file()
+ if not self._read and reading:
+ return self._read_error()
+ if not self.allow_update and writing:
+ return self._write_error()
+
+ if reading:
+ self._sync_io()
+ if not self.is_stream:
+ self.flush()
+ if not self._filesystem.is_windows_fs:
+ self.file_object.st_atime = helpers.now()
+ if truncate:
+ return self._truncate_wrapper()
+ if self._append:
+ if reading:
+ return self._read_wrappers(name)
+ elif not writing:
+ return self._other_wrapper(name)
+ if writing:
+ return self._write_wrapper(name)
+
+ return getattr(self._io, name)
+
+ def _read_error(self) -> Callable:
+ def read_error(*args, **kwargs):
+ """Throw an error unless the argument is zero."""
+ if args and args[0] == 0:
+ if self._filesystem.is_windows_fs and self.raw_io:
+ return b"" if self._binary else ""
+ self._raise("File is not open for reading.")
+
+ return read_error
+
+ def _write_error(self) -> Callable:
+ def write_error(*args, **kwargs):
+ """Throw an error."""
+ if self.raw_io:
+ if self._filesystem.is_windows_fs and args and len(args[0]) == 0:
+ return 0
+ self._raise("File is not open for writing.")
+
+ return write_error
+
+ def _is_open(self) -> bool:
+ if self.filedes is not None and self.filedes < len(self._filesystem.open_files):
+ open_files = self._filesystem.open_files[self.filedes]
+ if open_files is not None and self in open_files:
+ return True
+ return False
+
+ def _check_open_file(self) -> None:
+ if not self.is_stream and not self._is_open():
+ raise ValueError("I/O operation on closed file")
+
+ def __iter__(self) -> Union[Iterator[str], Iterator[bytes]]:
+ if not self._read:
+ self._raise("File is not open for reading")
+ return self._io.__iter__()
+
+ def __next__(self):
+ if not self._read:
+ self._raise("File is not open for reading")
+ return next(self._io)
+
+
+class StandardStreamWrapper:
+ """Wrapper for a system standard stream to be used in open files list."""
+
+ def __init__(self, stream_object: TextIO):
+ self._stream_object = stream_object
+ self.filedes: Optional[int] = None
+
+ def get_object(self) -> TextIO:
+ return self._stream_object
+
+ def fileno(self) -> int:
+ """Return the file descriptor of the wrapped standard stream."""
+ if self.filedes is not None:
+ return self.filedes
+ raise OSError(errno.EBADF, "Invalid file descriptor")
+
+ def read(self, n: int = -1) -> bytes:
+ return cast(bytes, self._stream_object.read())
+
+ def close(self) -> None:
+ """We do not support closing standard streams."""
+
+ def is_stream(self) -> bool:
+ return True
+
+
+class FakeDirWrapper:
+ """Wrapper for a FakeDirectory object to be used in open files list."""
+
+ def __init__(
+ self,
+ file_object: FakeDirectory,
+ file_path: AnyString,
+ filesystem: "FakeFilesystem",
+ ):
+ self.file_object = file_object
+ self.file_path = file_path
+ self._filesystem = filesystem
+ self.filedes: Optional[int] = None
+
+ def get_object(self) -> FakeDirectory:
+ """Return the FakeFile object that is wrapped by the current
+ instance."""
+ return self.file_object
+
+ def fileno(self) -> int:
+ """Return the file descriptor of the file object."""
+ if self.filedes is not None:
+ return self.filedes
+ raise OSError(errno.EBADF, "Invalid file descriptor")
+
+ def close(self) -> None:
+ """Close the directory."""
+ assert self.filedes is not None
+ self._filesystem._close_open_file(self.filedes)
+
+
+class FakePipeWrapper:
+ """Wrapper for a read or write descriptor of a real pipe object to be
+ used in open files list.
+ """
+
+ def __init__(
+ self,
+ filesystem: "FakeFilesystem",
+ fd: int,
+ can_write: bool,
+ mode: str = "",
+ ):
+ self._filesystem = filesystem
+ self.fd = fd # the real file descriptor
+ self.can_write = can_write
+ self.file_object = None
+ self.filedes: Optional[int] = None
+ self.real_file = None
+ if mode:
+ self.real_file = open(fd, mode)
+
+ def __enter__(self) -> "FakePipeWrapper":
+ """To support usage of this fake pipe with the 'with' statement."""
+ return self
+
+ def __exit__(
+ self,
+ exc_type: Optional[Type[BaseException]],
+ exc_val: Optional[BaseException],
+ exc_tb: Optional[TracebackType],
+ ) -> None:
+ """To support usage of this fake pipe with the 'with' statement."""
+ self.close()
+
+ def get_object(self) -> None:
+ return self.file_object
+
+ def fileno(self) -> int:
+ """Return the fake file descriptor of the pipe object."""
+ if self.filedes is not None:
+ return self.filedes
+ raise OSError(errno.EBADF, "Invalid file descriptor")
+
+ def read(self, numBytes: int = -1) -> bytes:
+ """Read from the real pipe."""
+ if self.real_file:
+ return self.real_file.read(numBytes) # pytype: disable=bad-return-type
+ return os.read(self.fd, numBytes)
+
+ def flush(self) -> None:
+ """Flush the real pipe?"""
+
+ def write(self, contents: bytes) -> int:
+ """Write to the real pipe."""
+ if self.real_file:
+ return self.real_file.write(contents)
+ return os.write(self.fd, contents)
+
+ def close(self) -> None:
+ """Close the pipe descriptor."""
+ assert self.filedes is not None
+ open_files = self._filesystem.open_files[self.filedes]
+ assert open_files is not None
+ open_files.remove(self)
+ if self.real_file:
+ self.real_file.close()
+ else:
+ os.close(self.fd)
+
+ def readable(self) -> bool:
+ """The pipe end can either be readable or writable."""
+ return not self.can_write
+
+ def writable(self) -> bool:
+ """The pipe end can either be readable or writable."""
+ return self.can_write
+
+ def seekable(self) -> bool:
+ """A pipe is not seekable."""
+ return False
diff --git a/pyfakefs/fake_filesystem.py b/pyfakefs/fake_filesystem.py
index 29bd1ba..9f170d1 100644
--- a/pyfakefs/fake_filesystem.py
+++ b/pyfakefs/fake_filesystem.py
@@ -14,24 +14,11 @@
"""A fake filesystem implementation for unit testing.
-:Includes:
- * :py:class:`FakeFile`: Provides the appearance of a real file.
- * :py:class:`FakeDirectory`: Provides the appearance of a real directory.
- * :py:class:`FakeFilesystem`: Provides the appearance of a real directory
- hierarchy.
- * :py:class:`FakeOsModule`: Uses :py:class:`FakeFilesystem` to provide a
- fake :py:mod:`os` module replacement.
- * :py:class:`FakeIoModule`: Uses :py:class:`FakeFilesystem` to provide a
- fake ``io`` module replacement.
- * :py:class:`FakePathModule`: Faked ``os.path`` module replacement.
- * :py:class:`FakeFileOpen`: Faked ``file()`` and ``open()`` function
- replacements.
-
:Usage:
->>> from pyfakefs import fake_filesystem
+>>> from pyfakefs import fake_filesystem, fake_os
>>> filesystem = fake_filesystem.FakeFilesystem()
->>> os_module = fake_filesystem.FakeOsModule(filesystem)
+>>> os_module = fake_os.FakeOsModule(filesystem)
>>> pathname = '/a/new/dir/new-file'
Create a new file object, creating parent directory objects as needed:
@@ -95,69 +82,48 @@ True
"""
import errno
import heapq
-import io
-import locale
import os
import random
import sys
-import traceback
-import uuid
-from collections import namedtuple
+import tempfile
+from collections import namedtuple, OrderedDict
from doctest import TestResults
from enum import Enum
from stat import (
- S_IFREG, S_IFDIR, S_ISLNK, S_IFMT, S_ISDIR, S_IFLNK, S_ISREG, S_IFSOCK
+ S_IFREG,
+ S_IFDIR,
+ S_ISLNK,
+ S_IFMT,
+ S_ISDIR,
+ S_IFLNK,
+ S_ISREG,
)
-from types import ModuleType, TracebackType
from typing import (
- List, Optional, Callable, Union, Any, Dict, Tuple, cast, AnyStr, overload,
- NoReturn, ClassVar, IO, Iterator, TextIO, Type
+ List,
+ Optional,
+ Callable,
+ Union,
+ Any,
+ Dict,
+ Tuple,
+ cast,
+ AnyStr,
+ overload,
+ NoReturn,
)
-from pyfakefs.deprecator import Deprecator
-from pyfakefs.extra_packages import use_scandir
-from pyfakefs.fake_scandir import scandir, walk, ScanDirIter
+
+from pyfakefs import fake_file, fake_path, fake_io, fake_os, helpers, fake_open
+from pyfakefs.fake_file import AnyFileWrapper, AnyFile
from pyfakefs.helpers import (
- FakeStatResult, BinaryBufferIO, TextBufferIO,
- is_int_type, is_byte_string, is_unicode_string, make_string_path,
- IS_PYPY, to_string, matching_string, real_encoding, now, AnyPath, to_bytes
-)
-from pyfakefs import __version__ # noqa: F401 for upwards compatibility
-
-PERM_READ = 0o400 # Read permission bit.
-PERM_WRITE = 0o200 # Write permission bit.
-PERM_EXE = 0o100 # Execute permission bit.
-PERM_DEF = 0o777 # Default permission bits.
-PERM_DEF_FILE = 0o666 # Default permission bits (regular file)
-PERM_ALL = 0o7777 # All permission bits.
-
-_OpenModes = namedtuple(
- '_OpenModes',
- 'must_exist can_read can_write truncate append must_not_exist'
+ is_int_type,
+ make_string_path,
+ to_string,
+ matching_string,
+ AnyPath,
+ AnyString,
)
-_OPEN_MODE_MAP = {
- # mode name:(file must exist, can read, can write,
- # truncate, append, must not exist)
- 'r': (True, True, False, False, False, False),
- 'w': (False, False, True, True, False, False),
- 'a': (False, False, True, False, True, False),
- 'r+': (True, True, True, False, False, False),
- 'w+': (False, True, True, True, False, False),
- 'a+': (False, True, True, False, True, False),
- 'x': (False, False, True, False, False, True),
- 'x+': (False, True, True, False, False, True)
-}
-
-AnyFileWrapper = Union[
- "FakeFileWrapper", "FakeDirWrapper",
- "StandardStreamWrapper", "FakePipeWrapper"
-]
-
-AnyString = Union[str, bytes]
-
-AnyFile = Union["FakeFile", "FakeDirectory"]
-
-if sys.platform.startswith('linux'):
+if sys.platform.startswith("linux"):
# on newer Linux system, the default maximum recursion depth is 40
# we ignore older systems here
_MAX_LINK_DEPTH = 40
@@ -165,726 +131,47 @@ else:
# on MacOS and Windows, the maximum recursion depth is 32
_MAX_LINK_DEPTH = 32
-NR_STD_STREAMS = 3
-if sys.platform == 'win32':
- USER_ID = 1
- GROUP_ID = 1
-else:
- USER_ID = os.getuid()
- GROUP_ID = os.getgid()
-
class OSType(Enum):
"""Defines the real or simulated OS of the underlying file system."""
+
LINUX = "linux"
MACOS = "macos"
WINDOWS = "windows"
-class PatchMode(Enum):
- """Defines if patching shall be on, off, or in automatic mode.
- Currently only used for `patch_open_code` option.
- """
- OFF = 1
- AUTO = 2
- ON = 3
-
-
-def set_uid(uid: int) -> None:
- """Set the global user id. This is used as st_uid for new files
- and to differentiate between a normal user and the root user (uid 0).
- For the root user, some permission restrictions are ignored.
-
- Args:
- uid: (int) the user ID of the user calling the file system functions.
- """
- global USER_ID
- USER_ID = uid
-
-
-def set_gid(gid: int) -> None:
- """Set the global group id. This is only used to set st_gid for new files,
- no permision checks are performed.
-
- Args:
- gid: (int) the group ID of the user calling the file system functions.
- """
- global GROUP_ID
- GROUP_ID = gid
-
-
-def reset_ids() -> None:
- """Set the global user ID and group ID back to default values."""
- if sys.platform == 'win32':
- set_uid(1)
- set_gid(1)
- else:
- set_uid(os.getuid())
- set_gid(os.getgid())
-
-
-def is_root() -> bool:
- """Return True if the current user is the root user."""
- return USER_ID == 0
-
-
-class FakeLargeFileIoException(Exception):
- """Exception thrown on unsupported operations for fake large files.
- Fake large files have a size with no real content.
- """
-
- def __init__(self, file_path: str) -> None:
- super(FakeLargeFileIoException, self).__init__(
- 'Read and write operations not supported for '
- 'fake large file: %s' % file_path)
-
-
-def _copy_module(old: ModuleType) -> ModuleType:
- """Recompiles and creates new module object."""
- saved = sys.modules.pop(old.__name__, None)
- new = __import__(old.__name__)
- if saved is not None:
- sys.modules[old.__name__] = saved
- return new
-
-
-class FakeFile:
- """Provides the appearance of a real file.
-
- Attributes currently faked out:
- * `st_mode`: user-specified, otherwise S_IFREG
- * `st_ctime`: the time.time() timestamp of the file change time (updated
- each time a file's attributes is modified).
- * `st_atime`: the time.time() timestamp when the file was last accessed.
- * `st_mtime`: the time.time() timestamp when the file was last modified.
- * `st_size`: the size of the file
- * `st_nlink`: the number of hard links to the file
- * `st_ino`: the inode number - a unique number identifying the file
- * `st_dev`: a unique number identifying the (fake) file system device
- the file belongs to
- * `st_uid`: always set to USER_ID, which can be changed globally using
- `set_uid`
- * `st_gid`: always set to GROUP_ID, which can be changed globally using
- `set_gid`
-
- .. note:: The resolution for `st_ctime`, `st_mtime` and `st_atime` in the
- real file system depends on the used file system (for example it is
- only 1s for HFS+ and older Linux file systems, but much higher for
- ext4 and NTFS). This is currently ignored by pyfakefs, which uses
- the resolution of `time.time()`.
-
- Under Windows, `st_atime` is not updated for performance reasons by
- default. pyfakefs never updates `st_atime` under Windows, assuming
- the default setting.
- """
- stat_types = (
- 'st_mode', 'st_ino', 'st_dev', 'st_nlink', 'st_uid', 'st_gid',
- 'st_size', 'st_atime', 'st_mtime', 'st_ctime',
- 'st_atime_ns', 'st_mtime_ns', 'st_ctime_ns'
- )
-
- def __init__(self, name: AnyStr,
- st_mode: int = S_IFREG | PERM_DEF_FILE,
- contents: Optional[AnyStr] = None,
- filesystem: Optional["FakeFilesystem"] = None,
- encoding: Optional[str] = None,
- errors: Optional[str] = None,
- side_effect: Optional[Callable[["FakeFile"], None]] = None):
- """
- Args:
- name: Name of the file/directory, without parent path information
- st_mode: The stat.S_IF* constant representing the file type (i.e.
- stat.S_IFREG, stat.S_IFDIR), and the file permissions.
- If no file type is set (e.g. permission flags only), a
- regular file type is assumed.
- contents: The contents of the filesystem object; should be a string
- or byte object for regular files, and a dict of other
- FakeFile or FakeDirectory objects wih the file names as
- keys for FakeDirectory objects
- filesystem: The fake filesystem where the file is created.
- encoding: If contents is a unicode string, the encoding used
- for serialization.
- errors: The error mode used for encoding/decoding errors.
- side_effect: function handle that is executed when file is written,
- must accept the file object as an argument.
- """
- # to be backwards compatible regarding argument order, we raise on None
- if filesystem is None:
- raise ValueError('filesystem shall not be None')
- self.filesystem: FakeFilesystem = filesystem
- self._side_effect: Optional[Callable] = side_effect
- self.name: AnyStr = name # type: ignore[assignment]
- self.stat_result = FakeStatResult(
- filesystem.is_windows_fs, USER_ID, GROUP_ID, now())
- if st_mode >> 12 == 0:
- st_mode |= S_IFREG
- self.stat_result.st_mode = st_mode
- self.st_size: int = 0
- self.encoding: Optional[str] = real_encoding(encoding)
- self.errors: str = errors or 'strict'
- self._byte_contents: Optional[bytes] = self._encode_contents(contents)
- self.stat_result.st_size = (
- len(self._byte_contents) if self._byte_contents is not None else 0)
- self.epoch: int = 0
- self.parent_dir: Optional[FakeDirectory] = None
- # Linux specific: extended file system attributes
- self.xattr: Dict = {}
- self.opened_as: AnyString = ''
-
- @property
- def byte_contents(self) -> Optional[bytes]:
- """Return the contents as raw byte array."""
- return self._byte_contents
-
- @property
- def contents(self) -> Optional[str]:
- """Return the contents as string with the original encoding."""
- if isinstance(self.byte_contents, bytes):
- return self.byte_contents.decode(
- self.encoding or locale.getpreferredencoding(False),
- errors=self.errors)
- return None
-
- @property
- def st_ctime(self) -> float:
- """Return the creation time of the fake file."""
- return self.stat_result.st_ctime
-
- @st_ctime.setter
- def st_ctime(self, val: float) -> None:
- """Set the creation time of the fake file."""
- self.stat_result.st_ctime = val
-
- @property
- def st_atime(self) -> float:
- """Return the access time of the fake file."""
- return self.stat_result.st_atime
-
- @st_atime.setter
- def st_atime(self, val: float) -> None:
- """Set the access time of the fake file."""
- self.stat_result.st_atime = val
-
- @property
- def st_mtime(self) -> float:
- """Return the modification time of the fake file."""
- return self.stat_result.st_mtime
-
- @st_mtime.setter
- def st_mtime(self, val: float) -> None:
- """Set the modification time of the fake file."""
- self.stat_result.st_mtime = val
-
- def set_large_file_size(self, st_size: int) -> None:
- """Sets the self.st_size attribute and replaces self.content with None.
-
- Provided specifically to simulate very large files without regards
- to their content (which wouldn't fit in memory).
- Note that read/write operations with such a file raise
- :py:class:`FakeLargeFileIoException`.
-
- Args:
- st_size: (int) The desired file size
-
- Raises:
- OSError: if the st_size is not a non-negative integer,
- or if st_size exceeds the available file system space
- """
- self._check_positive_int(st_size)
- if self.st_size:
- self.size = 0
- if self.filesystem:
- self.filesystem.change_disk_usage(st_size, self.name, self.st_dev)
- self.st_size = st_size
- self._byte_contents = None
-
- def _check_positive_int(self, size: int) -> None:
- # the size should be an positive integer value
- if not is_int_type(size) or size < 0:
- self.filesystem.raise_os_error(errno.ENOSPC, self.name)
-
- def is_large_file(self) -> bool:
- """Return `True` if this file was initialized with size
- but no contents.
- """
- return self._byte_contents is None
-
- def _encode_contents(
- self, contents: Union[str, bytes, None]) -> Optional[bytes]:
- if is_unicode_string(contents):
- contents = bytes(
- cast(str, contents),
- self.encoding or locale.getpreferredencoding(False),
- self.errors)
- return cast(bytes, contents)
-
- def set_initial_contents(self, contents: AnyStr) -> bool:
- """Sets the file contents and size.
- Called internally after initial file creation.
-
- Args:
- contents: string, new content of file.
-
- Returns:
- True if the contents have been changed.
-
- Raises:
- OSError: if the st_size is not a non-negative integer,
- or if st_size exceeds the available file system space
- """
- byte_contents = self._encode_contents(contents)
- changed = self._byte_contents != byte_contents
- st_size = len(byte_contents) if byte_contents else 0
-
- current_size = self.st_size or 0
- self.filesystem.change_disk_usage(
- st_size - current_size, self.name, self.st_dev)
- self._byte_contents = byte_contents
- self.st_size = st_size
- self.epoch += 1
- return changed
-
- def set_contents(self, contents: AnyStr,
- encoding: Optional[str] = None) -> bool:
- """Sets the file contents and size and increases the modification time.
- Also executes the side_effects if available.
-
- Args:
- contents: (str, bytes) new content of file.
- encoding: (str) the encoding to be used for writing the contents
- if they are a unicode string.
- If not given, the locale preferred encoding is used.
-
- Returns:
- True if the contents have been changed.
-
- Raises:
- OSError: if `st_size` is not a non-negative integer,
- or if it exceeds the available file system space.
- """
- self.encoding = real_encoding(encoding)
- changed = self.set_initial_contents(contents)
- if self._side_effect is not None:
- self._side_effect(self)
- return changed
-
- @property
- def size(self) -> int:
- """Return the size in bytes of the file contents.
- """
- return self.st_size
-
- @size.setter
- def size(self, st_size: int) -> None:
- """Resizes file content, padding with nulls if new size exceeds the
- old size.
-
- Args:
- st_size: The desired size for the file.
-
- Raises:
- OSError: if the st_size arg is not a non-negative integer
- or if st_size exceeds the available file system space
- """
-
- self._check_positive_int(st_size)
- current_size = self.st_size or 0
- self.filesystem.change_disk_usage(
- st_size - current_size, self.name, self.st_dev)
- if self._byte_contents:
- if st_size < current_size:
- self._byte_contents = self._byte_contents[:st_size]
- else:
- self._byte_contents += b'\0' * (st_size - current_size)
- self.st_size = st_size
- self.epoch += 1
-
- @property
- def path(self) -> AnyStr:
- """Return the full path of the current object."""
- names: List[AnyStr] = []
- obj: Optional[FakeFile] = self
- while obj:
- names.insert(
- 0, matching_string(self.name, obj.name)) # type: ignore
- obj = obj.parent_dir
- sep = self.filesystem.get_path_separator(names[0])
- if names[0] == sep:
- names.pop(0)
- dir_path = sep.join(names)
- drive = self.filesystem.splitdrive(dir_path)[0]
- # if a Windows path already starts with a drive or UNC path,
- # no extra separator is needed
- if not drive:
- dir_path = sep + dir_path
- else:
- dir_path = sep.join(names)
- return self.filesystem.absnormpath(dir_path)
-
- @Deprecator('property path')
- def GetPath(self):
- return self.path
-
- @Deprecator('property size')
- def GetSize(self):
- return self.size
-
- @Deprecator('property size')
- def SetSize(self, value):
- self.size = value
-
- @Deprecator('property st_atime')
- def SetATime(self, st_atime):
- """Set the self.st_atime attribute.
-
- Args:
- st_atime: The desired access time.
- """
- self.st_atime = st_atime
-
- @Deprecator('property st_mtime')
- def SetMTime(self, st_mtime):
- """Set the self.st_mtime attribute.
-
- Args:
- st_mtime: The desired modification time.
- """
- self.st_mtime = st_mtime
-
- @Deprecator('property st_ctime')
- def SetCTime(self, st_ctime):
- """Set the self.st_ctime attribute.
-
- Args:
- st_ctime: The desired creation time.
- """
- self.st_ctime = st_ctime
-
- def __getattr__(self, item: str) -> Any:
- """Forward some properties to stat_result."""
- if item in self.stat_types:
- return getattr(self.stat_result, item)
- return super().__getattribute__(item)
-
- def __setattr__(self, key: str, value: Any) -> None:
- """Forward some properties to stat_result."""
- if key in self.stat_types:
- return setattr(self.stat_result, key, value)
- return super().__setattr__(key, value)
-
- def __str__(self) -> str:
- return '%r(%o)' % (self.name, self.st_mode)
-
- @Deprecator('st_ino')
- def SetIno(self, st_ino):
- """Set the self.st_ino attribute.
- Note that a unique inode is assigned automatically to a new fake file.
- This function does not guarantee uniqueness and should be used with
- caution.
-
- Args:
- st_ino: (int) The desired inode.
- """
- self.st_ino = st_ino
-
-
-class FakeNullFile(FakeFile):
- def __init__(self, filesystem: "FakeFilesystem") -> None:
- devnull = 'nul' if filesystem.is_windows_fs else '/dev/null'
- super(FakeNullFile, self).__init__(
- devnull, filesystem=filesystem, contents='')
-
- @property
- def byte_contents(self) -> bytes:
- return b''
-
- def set_initial_contents(self, contents: AnyStr) -> bool:
- return False
-
-
-Deprecator.add(FakeFile, FakeFile.set_large_file_size, 'SetLargeFileSize')
-Deprecator.add(FakeFile, FakeFile.set_contents, 'SetContents')
-Deprecator.add(FakeFile, FakeFile.is_large_file, 'IsLargeFile')
-
-
-class FakeFileFromRealFile(FakeFile):
- """Represents a fake file copied from the real file system.
-
- The contents of the file are read on demand only.
- """
-
- def __init__(self, file_path: str, filesystem: "FakeFilesystem",
- side_effect: Optional[Callable] = None) -> None:
- """
- Args:
- file_path: Path to the existing file.
- filesystem: The fake filesystem where the file is created.
-
- Raises:
- OSError: if the file does not exist in the real file system.
- OSError: if the file already exists in the fake file system.
- """
- super().__init__(
- name=os.path.basename(file_path), filesystem=filesystem,
- side_effect=side_effect)
- self.contents_read = False
-
- @property
- def byte_contents(self) -> Optional[bytes]:
- if not self.contents_read:
- self.contents_read = True
- with io.open(self.file_path, 'rb') as f:
- self._byte_contents = f.read()
- # On MacOS and BSD, the above io.open() updates atime on the real file
- self.st_atime = os.stat(self.file_path).st_atime
- return self._byte_contents
-
- def set_contents(self, contents, encoding=None):
- self.contents_read = True
- super(FakeFileFromRealFile, self).set_contents(contents, encoding)
-
- def is_large_file(self):
- """The contents are never faked."""
- return False
-
-
-class FakeDirectory(FakeFile):
- """Provides the appearance of a real directory."""
-
- def __init__(self, name: str, perm_bits: int = PERM_DEF,
- filesystem: Optional["FakeFilesystem"] = None):
- """
- Args:
- name: name of the file/directory, without parent path information
- perm_bits: permission bits. defaults to 0o777.
- filesystem: if set, the fake filesystem where the directory
- is created
- """
- FakeFile.__init__(
- self, name, S_IFDIR | perm_bits, '', filesystem=filesystem)
- # directories have the link count of contained entries,
- # including '.' and '..'
- self.st_nlink += 1
- self._entries: Dict[str, AnyFile] = {}
-
- def set_contents(self, contents: AnyStr,
- encoding: Optional[str] = None) -> bool:
- raise self.filesystem.raise_os_error(errno.EISDIR, self.path)
-
- @property
- def entries(self) -> Dict[str, FakeFile]:
- """Return the list of contained directory entries."""
- return self._entries
-
- @property
- def ordered_dirs(self) -> List[str]:
- """Return the list of contained directory entry names ordered by
- creation order.
- """
- return [item[0] for item in sorted(
- self._entries.items(), key=lambda entry: entry[1].st_ino)]
-
- def add_entry(self, path_object: FakeFile) -> None:
- """Adds a child FakeFile to this directory.
-
- Args:
- path_object: FakeFile instance to add as a child of this directory.
-
- Raises:
- OSError: if the directory has no write permission (Posix only)
- OSError: if the file or directory to be added already exists
- """
- if (not is_root() and not self.st_mode & PERM_WRITE and
- not self.filesystem.is_windows_fs):
- raise OSError(errno.EACCES, 'Permission Denied', self.path)
-
- path_object_name: str = to_string(path_object.name)
- if path_object_name in self.entries:
- self.filesystem.raise_os_error(errno.EEXIST, self.path)
-
- self._entries[path_object_name] = path_object
- path_object.parent_dir = self
- if path_object.st_ino is None:
- self.filesystem.last_ino += 1
- path_object.st_ino = self.filesystem.last_ino
- self.st_nlink += 1
- path_object.st_nlink += 1
- path_object.st_dev = self.st_dev
- if path_object.st_nlink == 1:
- self.filesystem.change_disk_usage(
- path_object.size, path_object.name, self.st_dev)
-
- def get_entry(self, pathname_name: str) -> AnyFile:
- """Retrieves the specified child file or directory entry.
-
- Args:
- pathname_name: The basename of the child object to retrieve.
-
- Returns:
- The fake file or directory object.
-
- Raises:
- KeyError: if no child exists by the specified name.
- """
- pathname_name = self._normalized_entryname(pathname_name)
- return self.entries[to_string(pathname_name)]
-
- def _normalized_entryname(self, pathname_name: str) -> str:
- if not self.filesystem.is_case_sensitive:
- matching_names = [name for name in self.entries
- if name.lower() == pathname_name.lower()]
- if matching_names:
- pathname_name = matching_names[0]
- return pathname_name
-
- def remove_entry(self, pathname_name: str, recursive: bool = True) -> None:
- """Removes the specified child file or directory.
-
- Args:
- pathname_name: Basename of the child object to remove.
- recursive: If True (default), the entries in contained directories
- are deleted first. Used to propagate removal errors
- (e.g. permission problems) from contained entries.
-
- Raises:
- KeyError: if no child exists by the specified name.
- OSError: if user lacks permission to delete the file,
- or (Windows only) the file is open.
- """
- pathname_name = self._normalized_entryname(pathname_name)
- entry = self.get_entry(pathname_name)
- if self.filesystem.is_windows_fs:
- if entry.st_mode & PERM_WRITE == 0:
- self.filesystem.raise_os_error(errno.EACCES, pathname_name)
- if self.filesystem.has_open_file(entry):
- self.filesystem.raise_os_error(errno.EACCES, pathname_name)
- else:
- if (not is_root() and (self.st_mode & (PERM_WRITE | PERM_EXE) !=
- PERM_WRITE | PERM_EXE)):
- self.filesystem.raise_os_error(errno.EACCES, pathname_name)
-
- if recursive and isinstance(entry, FakeDirectory):
- while entry.entries:
- entry.remove_entry(list(entry.entries)[0])
- elif entry.st_nlink == 1:
- self.filesystem.change_disk_usage(
- -entry.size, pathname_name, entry.st_dev)
-
- self.st_nlink -= 1
- entry.st_nlink -= 1
- assert entry.st_nlink >= 0
-
- del self.entries[to_string(pathname_name)]
-
- @property
- def size(self) -> int:
- """Return the total size of all files contained in this directory tree.
- """
- return sum([item[1].size for item in self.entries.items()])
-
- @size.setter
- def size(self, st_size: int) -> None:
- """Setting the size is an error for a directory."""
- raise self.filesystem.raise_os_error(errno.EISDIR, self.path)
-
- @Deprecator('property size')
- def GetSize(self):
- return self.size
-
- def has_parent_object(self, dir_object: "FakeDirectory") -> bool:
- """Return `True` if dir_object is a direct or indirect parent
- directory, or if both are the same object."""
- obj: Optional[FakeDirectory] = self
- while obj:
- if obj == dir_object:
- return True
- obj = obj.parent_dir
- return False
-
- def __str__(self) -> str:
- description = super(FakeDirectory, self).__str__() + ':\n'
- for item in self.entries:
- item_desc = self.entries[item].__str__()
- for line in item_desc.split('\n'):
- if line:
- description = description + ' ' + line + '\n'
- return description
-
-
-Deprecator.add(FakeDirectory, FakeDirectory.add_entry, 'AddEntry')
-Deprecator.add(FakeDirectory, FakeDirectory.get_entry, 'GetEntry')
-Deprecator.add(FakeDirectory, FakeDirectory.set_contents, 'SetContents')
-Deprecator.add(FakeDirectory, FakeDirectory.remove_entry, 'RemoveEntry')
-
-
-class FakeDirectoryFromRealDirectory(FakeDirectory):
- """Represents a fake directory copied from the real file system.
-
- The contents of the directory are read on demand only.
- """
-
- def __init__(self, source_path: AnyPath, filesystem: "FakeFilesystem",
- read_only: bool, target_path: Optional[AnyPath] = None):
- """
- Args:
- source_path: Full directory path.
- filesystem: The fake filesystem where the directory is created.
- read_only: If set, all files under the directory are treated
- as read-only, e.g. a write access raises an exception;
- otherwise, writing to the files changes the fake files
- only as usually.
- target_path: If given, the target path of the directory,
- otherwise the target is the same as `source_path`.
-
- Raises:
- OSError: if the directory does not exist in the real file system
- """
- target_path = target_path or source_path
- real_stat = os.stat(source_path)
- super(FakeDirectoryFromRealDirectory, self).__init__(
- name=to_string(os.path.split(target_path)[1]),
- perm_bits=real_stat.st_mode,
- filesystem=filesystem)
-
- self.st_ctime = real_stat.st_ctime
- self.st_atime = real_stat.st_atime
- self.st_mtime = real_stat.st_mtime
- self.st_gid = real_stat.st_gid
- self.st_uid = real_stat.st_uid
- self.source_path = source_path # type: ignore
- self.read_only = read_only
- self.contents_read = False
-
- @property
- def entries(self) -> Dict[str, FakeFile]:
- """Return the list of contained directory entries, loading them
- if not already loaded."""
- if not self.contents_read:
- self.contents_read = True
- base = self.path
- for entry in os.listdir(self.source_path):
- source_path = os.path.join(self.source_path, entry)
- target_path = os.path.join(base, entry) # type: ignore
- if os.path.islink(source_path):
- self.filesystem.add_real_symlink(source_path, target_path)
- elif os.path.isdir(source_path):
- self.filesystem.add_real_directory(
- source_path, self.read_only, target_path=target_path)
- else:
- self.filesystem.add_real_file(
- source_path, self.read_only, target_path=target_path)
- return self._entries
-
- @property
- def size(self) -> int:
- # we cannot get the size until the contents are loaded
- if not self.contents_read:
- return 0
- return super(FakeDirectoryFromRealDirectory, self).size
-
- @size.setter
- def size(self, st_size: int) -> None:
- raise self.filesystem.raise_os_error(errno.EISDIR, self.path)
+# definitions for backwards compatibility
+FakeFile = fake_file.FakeFile
+FakeNullFile = fake_file.FakeNullFile
+FakeFileFromRealFile = fake_file.FakeFileFromRealFile
+FakeDirectory = fake_file.FakeDirectory
+FakeDirectoryFromRealDirectory = fake_file.FakeDirectoryFromRealDirectory
+FakeFileWrapper = fake_file.FakeFileWrapper
+StandardStreamWrapper = fake_file.StandardStreamWrapper
+FakeDirWrapper = fake_file.FakeDirWrapper
+FakePipeWrapper = fake_file.FakePipeWrapper
+
+FakePathModule = fake_path.FakePathModule
+FakeOsModule = fake_os.FakeOsModule
+FakeFileOpen = fake_open.FakeFileOpen
+FakeIoModule = fake_io.FakeIoModule
+if sys.platform != "win32":
+ FakeFcntlModule = fake_io.FakeFcntlModule
+PatchMode = fake_io.PatchMode
+
+is_root = helpers.is_root
+get_uid = helpers.get_uid
+set_uid = helpers.set_uid
+get_gid = helpers.get_gid
+set_gid = helpers.set_gid
+reset_ids = helpers.reset_ids
+
+PERM_READ = helpers.PERM_READ
+PERM_WRITE = helpers.PERM_WRITE
+PERM_EXE = helpers.PERM_EXE
+PERM_DEF = helpers.PERM_DEF
+PERM_DEF_FILE = helpers.PERM_DEF_FILE
+PERM_ALL = helpers.PERM_ALL
class FakeFilesystem:
@@ -897,20 +184,31 @@ class FakeFilesystem:
is_macos: `True` under MacOS, or if we are faking it.
is_case_sensitive: `True` if a case-sensitive file system is assumed.
root: The root :py:class:`FakeDirectory` entry of the file system.
- cwd: The current working directory path.
umask: The umask used for newly created files, see `os.umask`.
patcher: Holds the Patcher object if created from it. Allows access
to the patcher object if using the pytest fs fixture.
+ patch_open_code: Defines how `io.open_code` will be patched;
+ patching can be on, off, or in automatic mode.
+ shuffle_listdir_results: If `True`, `os.listdir` will not sort the
+ results to match the real file system behavior.
"""
- def __init__(self, path_separator: str = os.path.sep,
- total_size: int = None,
- patcher: Any = None) -> None:
+ def __init__(
+ self,
+ path_separator: str = os.path.sep,
+ total_size: Optional[int] = None,
+ patcher: Any = None,
+ create_temp_dir: bool = False,
+ ) -> None:
"""
Args:
path_separator: optional substitute for os.path.sep
total_size: if not None, the total size in bytes of the
root filesystem.
+ patcher: the Patcher instance if created from the Patcher
+ create_temp_dir: If True, a temp directory is created on initialization.
+ Under Posix, if the temp directory is not `/tmp`, a link to the temp
+ path is additionally created at `/tmp`.
Example usage to use the same path separator under all systems:
@@ -920,6 +218,7 @@ class FakeFilesystem:
self.path_separator: str = path_separator
self.alternative_path_separator: Optional[str] = os.path.altsep
self.patcher = patcher
+ self.create_temp_dir = create_temp_dir
if path_separator != os.sep:
self.alternative_path_separator = None
@@ -927,20 +226,20 @@ class FakeFilesystem:
# Windows fs on non-Windows systems and vice verse;
# is it used to support drive letters, UNC paths and some other
# Windows-specific features
- self.is_windows_fs = sys.platform == 'win32'
+ self._is_windows_fs = sys.platform == "win32"
# can be used to test some MacOS-specific behavior under other systems
- self.is_macos = sys.platform == 'darwin'
+ self._is_macos = sys.platform == "darwin"
# is_case_sensitive can be used to test pyfakefs for case-sensitive
# file systems on non-case-sensitive systems and vice verse
- self.is_case_sensitive = not (self.is_windows_fs or self.is_macos)
+ self.is_case_sensitive: bool = not (self.is_windows_fs or self._is_macos)
- self.root = FakeDirectory(self.path_separator, filesystem=self)
- self.cwd = self.root.name
+ self.root: FakeDirectory
+ self._cwd = ""
# We can't query the current value without changing it:
- self.umask = os.umask(0o22)
+ self.umask: int = os.umask(0o22)
os.umask(self.umask)
# A list of open file objects. Their position in the list is their
@@ -949,12 +248,12 @@ class FakeFilesystem:
# A heap containing all free positions in self.open_files list
self._free_fd_heap: List[int] = []
# last used numbers for inodes (st_ino) and devices (st_dev)
- self.last_ino = 0
- self.last_dev = 0
- self.mount_points: Dict[AnyString, Dict] = {}
- self.add_mount_point(self.root.name, total_size)
- self._add_standard_streams()
- self.dev_null = FakeNullFile(self)
+ self.last_ino: int = 0
+ self.last_dev: int = 0
+ self.mount_points: Dict[AnyString, Dict] = OrderedDict()
+ self.dev_null: Any = None
+ self.reset(total_size=total_size, init_pathlib=False)
+
# set from outside if needed
self.patch_open_code = PatchMode.OFF
self.shuffle_listdir_results = False
@@ -964,38 +263,105 @@ class FakeFilesystem:
return not self.is_windows_fs and not self.is_macos
@property
+ def is_windows_fs(self) -> bool:
+ return self._is_windows_fs
+
+ @is_windows_fs.setter
+ def is_windows_fs(self, value: bool) -> None:
+ if self._is_windows_fs != value:
+ self._is_windows_fs = value
+ self.reset()
+ FakePathModule.reset(self)
+
+ @property
+ def is_macos(self) -> bool:
+ return self._is_macos
+
+ @is_macos.setter
+ def is_macos(self, value: bool) -> None:
+ if self._is_macos != value:
+ self._is_macos = value
+ self.reset()
+ FakePathModule.reset(self)
+
+ @property
+ def cwd(self) -> str:
+ """Return the current working directory of the fake filesystem."""
+ return self._cwd
+
+ @cwd.setter
+ def cwd(self, value: str) -> None:
+ """Set the current working directory of the fake filesystem.
+ Make sure a new drive or share is auto-mounted under Windows.
+ """
+ self._cwd = value
+ self._auto_mount_drive_if_needed(value)
+
+ @property
+ def root_dir(self) -> FakeDirectory:
+ """Return the root directory, which represents "/" under POSIX,
+ and the current drive under Windows."""
+ if self.is_windows_fs:
+ return self._mount_point_dir_for_cwd()
+ return self.root
+
+ @property
+ def root_dir_name(self) -> str:
+ """Return the root directory name, which is "/" under POSIX,
+ and the root path of the current drive under Windows."""
+ root_dir = to_string(self.root_dir.name)
+ if not root_dir.endswith(self.path_separator):
+ return root_dir + self.path_separator
+ return root_dir
+
+ @property
def os(self) -> OSType:
"""Return the real or simulated type of operating system."""
- return (OSType.WINDOWS if self.is_windows_fs else
- OSType.MACOS if self.is_macos else OSType.LINUX)
+ return (
+ OSType.WINDOWS
+ if self.is_windows_fs
+ else OSType.MACOS
+ if self.is_macos
+ else OSType.LINUX
+ )
@os.setter
def os(self, value: OSType) -> None:
"""Set the simulated type of operating system underlying the fake
file system."""
- self.is_windows_fs = value == OSType.WINDOWS
- self.is_macos = value == OSType.MACOS
+ self._is_windows_fs = value == OSType.WINDOWS
+ self._is_macos = value == OSType.MACOS
self.is_case_sensitive = value == OSType.LINUX
- self.path_separator = '\\' if value == OSType.WINDOWS else '/'
- self.alternative_path_separator = ('/' if value == OSType.WINDOWS
- else None)
+ self.path_separator = "\\" if value == OSType.WINDOWS else "/"
+ self.alternative_path_separator = "/" if value == OSType.WINDOWS else None
self.reset()
FakePathModule.reset(self)
- def reset(self, total_size: Optional[int] = None):
+ def reset(self, total_size: Optional[int] = None, init_pathlib: bool = True):
"""Remove all file system contents and reset the root."""
self.root = FakeDirectory(self.path_separator, filesystem=self)
- self.cwd = self.root.name
- self.open_files = []
- self._free_fd_heap = []
+ self.dev_null = FakeNullFile(self)
+ self.open_files.clear()
+ self._free_fd_heap.clear()
self.last_ino = 0
self.last_dev = 0
- self.mount_points = {}
- self.add_mount_point(self.root.name, total_size)
+ self.mount_points.clear()
+ self._add_root_mount_point(total_size)
self._add_standard_streams()
- from pyfakefs import fake_pathlib
- fake_pathlib.init_module(self)
+ if self.create_temp_dir:
+ self._create_temp_dir()
+ if init_pathlib:
+ from pyfakefs import fake_pathlib
+
+ fake_pathlib.init_module(self)
+
+ def _add_root_mount_point(self, total_size):
+ mount_point = "C:" if self.is_windows_fs else self.path_separator
+ self._cwd = mount_point
+ if not self.cwd.endswith(self.path_separator):
+ self._cwd += self.path_separator
+ self.add_mount_point(mount_point, total_size)
def pause(self) -> None:
"""Pause the patching of the file system modules until `resume` is
@@ -1009,8 +375,10 @@ class FakeFilesystem:
RuntimeError: if the file system was not created by a Patcher.
"""
if self.patcher is None:
- raise RuntimeError('pause() can only be called from a fake file '
- 'system object created by a Patcher object')
+ raise RuntimeError(
+ "pause() can only be called from a fake file "
+ "system object created by a Patcher object"
+ )
self.patcher.pause()
def resume(self) -> None:
@@ -1022,8 +390,10 @@ class FakeFilesystem:
RuntimeError: if the file system has not been created by `Patcher`.
"""
if self.patcher is None:
- raise RuntimeError('resume() can only be called from a fake file '
- 'system object created by a Patcher object')
+ raise RuntimeError(
+ "resume() can only be called from a fake file "
+ "system object created by a Patcher object"
+ )
self.patcher.resume()
def clear_cache(self) -> None:
@@ -1032,14 +402,14 @@ class FakeFilesystem:
self.patcher.clear_cache()
def line_separator(self) -> str:
- return '\r\n' if self.is_windows_fs else '\n'
-
- def _error_message(self, err_no: int) -> str:
- return os.strerror(err_no) + ' in the fake filesystem'
-
- def raise_os_error(self, err_no: int,
- filename: Optional[AnyString] = None,
- winerror: Optional[int] = None) -> NoReturn:
+ return "\r\n" if self.is_windows_fs else "\n"
+
+ def raise_os_error(
+ self,
+ err_no: int,
+ filename: Optional[AnyString] = None,
+ winerror: Optional[int] = None,
+ ) -> NoReturn:
"""Raises OSError.
The error message is constructed from the given error code and shall
start with the error string issued in the real system.
@@ -1052,9 +422,8 @@ class FakeFilesystem:
filename: The name of the affected file, if any.
winerror: Windows only - the specific Windows error code.
"""
- message = self._error_message(err_no)
- if (winerror is not None and sys.platform == 'win32' and
- self.is_windows_fs):
+ message = os.strerror(err_no) + " in the fake filesystem"
+ if winerror is not None and sys.platform == "win32" and self.is_windows_fs:
raise OSError(err_no, message, filename, winerror)
raise OSError(err_no, message, filename)
@@ -1062,20 +431,22 @@ class FakeFilesystem:
"""Return the path separator as the same type as path"""
return matching_string(path, self.path_separator)
- def _alternative_path_separator(
- self, path: AnyStr) -> Optional[AnyStr]:
+ def _alternative_path_separator(self, path: AnyStr) -> Optional[AnyStr]:
"""Return the alternative path separator as the same type as path"""
return matching_string(path, self.alternative_path_separator)
- def _starts_with_sep(self, path: AnyStr) -> bool:
+ def starts_with_sep(self, path: AnyStr) -> bool:
"""Return True if path starts with a path separator."""
sep = self.get_path_separator(path)
altsep = self._alternative_path_separator(path)
- return (path.startswith(sep) or altsep is not None and
- path.startswith(altsep))
-
- def add_mount_point(self, path: AnyStr,
- total_size: Optional[int] = None) -> Dict:
+ return path.startswith(sep) or altsep is not None and path.startswith(altsep)
+
+ def add_mount_point(
+ self,
+ path: AnyStr,
+ total_size: Optional[int] = None,
+ can_exist: bool = False,
+ ) -> Dict:
"""Add a new mount point for a filesystem device.
The mount point gets a new unique device number.
@@ -1085,36 +456,75 @@ class FakeFilesystem:
total_size: The new total size of the added filesystem device
in bytes. Defaults to infinite size.
+ can_exist: If True, no error is raised if the mount point
+ already exists
+
Returns:
The newly created mount point dict.
Raises:
- OSError: if trying to mount an existing mount point again.
+ OSError: if trying to mount an existing mount point again,
+ and `can_exist` is False.
"""
- path = self.absnormpath(path)
- if path in self.mount_points:
- self.raise_os_error(errno.EEXIST, path)
+ path = self.normpath(self.normcase(path))
+ for mount_point in self.mount_points:
+ if (
+ self.is_case_sensitive
+ and path == matching_string(path, mount_point)
+ or not self.is_case_sensitive
+ and path.lower() == matching_string(path, mount_point.lower())
+ ):
+ if can_exist:
+ return self.mount_points[mount_point]
+ self.raise_os_error(errno.EEXIST, path)
+
self.last_dev += 1
self.mount_points[path] = {
- 'idev': self.last_dev, 'total_size': total_size, 'used_size': 0
+ "idev": self.last_dev,
+ "total_size": total_size,
+ "used_size": 0,
}
- # special handling for root path: has been created before
- if path == self.root.name:
+ if path == matching_string(path, self.root.name):
+ # special handling for root path: has been created before
root_dir = self.root
self.last_ino += 1
root_dir.st_ino = self.last_ino
else:
- root_dir = self.create_dir(path)
+ root_dir = self._create_mount_point_dir(path)
root_dir.st_dev = self.last_dev
return self.mount_points[path]
- def _auto_mount_drive_if_needed(self, path: AnyStr,
- force: bool = False) -> Optional[Dict]:
- if (self.is_windows_fs and
- (force or not self._mount_point_for_path(path))):
+ def _create_mount_point_dir(self, directory_path: AnyPath) -> FakeDirectory:
+ """A version of `create_dir` for the mount point directory creation,
+ which avoids circular calls and unneeded checks.
+ """
+ dir_path = self.make_string_path(directory_path)
+ path_components = self._path_components(dir_path)
+ current_dir = self.root
+
+ new_dirs = []
+ for component in [to_string(p) for p in path_components]:
+ directory = self._directory_content(current_dir, to_string(component))[1]
+ if not directory:
+ new_dir = FakeDirectory(component, filesystem=self)
+ new_dirs.append(new_dir)
+ current_dir.add_entry(new_dir)
+ current_dir = new_dir
+ else:
+ current_dir = cast(FakeDirectory, directory)
+
+ for new_dir in new_dirs:
+ new_dir.st_mode = S_IFDIR | helpers.PERM_DEF
+
+ return current_dir
+
+ def _auto_mount_drive_if_needed(self, path: AnyStr) -> Optional[Dict]:
+ """Windows only: if `path` is located on an unmounted drive or UNC
+ mount point, the drive/mount point is added to the mount points."""
+ if self.is_windows_fs:
drive = self.splitdrive(path)[0]
if drive:
- return self.add_mount_point(path=drive)
+ return self.add_mount_point(path=drive, can_exist=True)
return None
def _mount_point_for_path(self, path: AnyStr) -> Dict:
@@ -1122,7 +532,7 @@ class FakeFilesystem:
for mount_path in self.mount_points:
if path == matching_string(path, mount_path):
return self.mount_points[mount_path]
- mount_path = matching_string(path, '')
+ mount_path = matching_string(path, "")
drive = self.splitdrive(path)[0]
for root_path in self.mount_points:
root_path = matching_string(path, root_path)
@@ -1132,18 +542,42 @@ class FakeFilesystem:
mount_path = root_path
if mount_path:
return self.mount_points[to_string(mount_path)]
- mount_point = self._auto_mount_drive_if_needed(path, force=True)
+ mount_point = self._auto_mount_drive_if_needed(path)
assert mount_point
return mount_point
+ def _mount_point_dir_for_cwd(self) -> FakeDirectory:
+ """Return the fake directory object of the mount point where the
+ current working directory points to."""
+
+ def object_from_path(file_path) -> FakeDirectory:
+ path_components = self._path_components(file_path)
+ target = self.root
+ for component in path_components:
+ target = cast(FakeDirectory, target.get_entry(component))
+ return target
+
+ path = to_string(self.cwd)
+ for mount_path in self.mount_points:
+ if path == to_string(mount_path):
+ return object_from_path(mount_path)
+ mount_path = ""
+ drive = to_string(self.splitdrive(path)[0])
+ for root_path in self.mount_points:
+ str_root_path = to_string(root_path)
+ if drive and not str_root_path.startswith(drive):
+ continue
+ if path.startswith(str_root_path) and len(str_root_path) > len(mount_path):
+ mount_path = root_path
+ return object_from_path(mount_path)
+
def _mount_point_for_device(self, idev: int) -> Optional[Dict]:
for mount_point in self.mount_points.values():
- if mount_point['idev'] == idev:
+ if mount_point["idev"] == idev:
return mount_point
return None
- def get_disk_usage(
- self, path: AnyStr = None) -> Tuple[int, int, int]:
+ def get_disk_usage(self, path: Optional[AnyStr] = None) -> Tuple[int, int, int]:
"""Return the total, used and free disk space in bytes as named tuple,
or placeholder values simulating unlimited space if not set.
@@ -1154,21 +588,21 @@ class FakeFilesystem:
`path` resides.
Defaults to the root path (e.g. '/' on Unix systems).
"""
- DiskUsage = namedtuple('DiskUsage', 'total, used, free')
+ DiskUsage = namedtuple("DiskUsage", "total, used, free")
if path is None:
- mount_point = self.mount_points[self.root.name]
+ mount_point = next(iter(self.mount_points.values()))
else:
- mount_point = self._mount_point_for_path(path)
- if mount_point and mount_point['total_size'] is not None:
- return DiskUsage(mount_point['total_size'],
- mount_point['used_size'],
- mount_point['total_size'] -
- mount_point['used_size'])
- return DiskUsage(
- 1024 * 1024 * 1024 * 1024, 0, 1024 * 1024 * 1024 * 1024)
-
- def set_disk_usage(
- self, total_size: int, path: Optional[AnyStr] = None) -> None:
+ file_path = make_string_path(path)
+ mount_point = self._mount_point_for_path(file_path)
+ if mount_point and mount_point["total_size"] is not None:
+ return DiskUsage(
+ mount_point["total_size"],
+ mount_point["used_size"],
+ mount_point["total_size"] - mount_point["used_size"],
+ )
+ return DiskUsage(1024 * 1024 * 1024 * 1024, 0, 1024 * 1024 * 1024 * 1024)
+
+ def set_disk_usage(self, total_size: int, path: Optional[AnyStr] = None) -> None:
"""Changes the total size of the file system, preserving the
used space.
Example usage: set the size of an auto-mounted Windows drive.
@@ -1183,16 +617,20 @@ class FakeFilesystem:
Raises:
OSError: if the new space is smaller than the used size.
"""
- file_path: AnyStr = (path if path is not None # type: ignore
- else self.root.name)
+ file_path: AnyStr = (
+ path if path is not None else self.root_dir_name # type: ignore
+ )
mount_point = self._mount_point_for_path(file_path)
- if (mount_point['total_size'] is not None and
- mount_point['used_size'] > total_size):
+ if (
+ mount_point["total_size"] is not None
+ and mount_point["used_size"] > total_size
+ ):
self.raise_os_error(errno.ENOSPC, path)
- mount_point['total_size'] = total_size
+ mount_point["total_size"] = total_size
- def change_disk_usage(self, usage_change: int,
- file_path: AnyStr, st_dev: int) -> None:
+ def change_disk_usage(
+ self, usage_change: int, file_path: AnyStr, st_dev: int
+ ) -> None:
"""Change the used disk space by the given amount.
Args:
@@ -1208,14 +646,13 @@ class FakeFilesystem:
"""
mount_point = self._mount_point_for_device(st_dev)
if mount_point:
- total_size = mount_point['total_size']
+ total_size = mount_point["total_size"]
if total_size is not None:
- if total_size - mount_point['used_size'] < usage_change:
+ if total_size - mount_point["used_size"] < usage_change:
self.raise_os_error(errno.ENOSPC, file_path)
- mount_point['used_size'] += usage_change
+ mount_point["used_size"] += usage_change
- def stat(self, entry_path: AnyStr,
- follow_symlinks: bool = True):
+ def stat(self, entry_path: AnyStr, follow_symlinks: bool = True):
"""Return the os.stat-like tuple for the FakeFile object of entry_path.
Args:
@@ -1232,8 +669,11 @@ class FakeFilesystem:
# stat should return the tuple representing return value of os.stat
try:
file_object = self.resolve(
- entry_path, follow_symlinks,
- allow_fd=True, check_read_perm=False)
+ entry_path,
+ follow_symlinks,
+ allow_fd=True,
+ check_read_perm=False,
+ )
except TypeError:
file_object = self.resolve(entry_path)
if not is_root():
@@ -1243,15 +683,18 @@ class FakeFilesystem:
self.get_object(parent_dir.path) # type: ignore[arg-type]
self.raise_for_filepath_ending_with_separator(
- entry_path, file_object, follow_symlinks)
+ entry_path, file_object, follow_symlinks
+ )
return file_object.stat_result.copy()
def raise_for_filepath_ending_with_separator(
- self, entry_path: AnyStr,
- file_object: FakeFile,
- follow_symlinks: bool = True,
- macos_handling: bool = False) -> None:
+ self,
+ entry_path: AnyStr,
+ file_object: FakeFile,
+ follow_symlinks: bool = True,
+ macos_handling: bool = False,
+ ) -> None:
if self.ends_with_path_separator(entry_path):
if S_ISLNK(file_object.st_mode):
try:
@@ -1271,12 +714,16 @@ class FakeFilesystem:
else:
is_error = not S_ISDIR(file_object.st_mode)
if is_error:
- error_nr = (errno.EINVAL if self.is_windows_fs
- else errno.ENOTDIR)
+ error_nr = errno.EINVAL if self.is_windows_fs else errno.ENOTDIR
self.raise_os_error(error_nr, entry_path)
- def chmod(self, path: AnyStr, mode: int,
- follow_symlinks: bool = True) -> None:
+ def chmod(
+ self,
+ path: AnyStr,
+ mode: int,
+ follow_symlinks: bool = True,
+ force_unix_mode: bool = False,
+ ) -> None:
"""Change the permissions of a file as encoded in integer mode.
Args:
@@ -1284,22 +731,31 @@ class FakeFilesystem:
mode: (int) Permissions.
follow_symlinks: If `False` and `path` points to a symlink,
the link itself is affected instead of the linked object.
+ force_unix_mode: if True and run under Windows, the mode is not
+ adapted for Windows to allow making dirs unreadable
"""
- file_object = self.resolve(path, follow_symlinks, allow_fd=True)
- if self.is_windows_fs:
- if mode & PERM_WRITE:
+ file_object = self.resolve(
+ path, follow_symlinks, allow_fd=True, check_owner=True
+ )
+ if self.is_windows_fs and not force_unix_mode:
+ if mode & helpers.PERM_WRITE:
file_object.st_mode = file_object.st_mode | 0o222
else:
file_object.st_mode = file_object.st_mode & 0o777555
else:
- file_object.st_mode = ((file_object.st_mode & ~PERM_ALL) |
- (mode & PERM_ALL))
- file_object.st_ctime = now()
-
- def utime(self, path: AnyStr,
- times: Optional[Tuple[Union[int, float], Union[int, float]]] =
- None, *, ns: Optional[Tuple[int, int]] = None,
- follow_symlinks: bool = True) -> None:
+ file_object.st_mode = (file_object.st_mode & ~helpers.PERM_ALL) | (
+ mode & helpers.PERM_ALL
+ )
+ file_object.st_ctime = helpers.now()
+
+ def utime(
+ self,
+ path: AnyStr,
+ times: Optional[Tuple[Union[int, float], Union[int, float]]] = None,
+ *,
+ ns: Optional[Tuple[int, int]] = None,
+ follow_symlinks: bool = True,
+ ) -> None:
"""Change the access and modified times of a file.
Args:
@@ -1325,50 +781,37 @@ class FakeFilesystem:
if times is not None:
for file_time in times:
if not isinstance(file_time, (int, float)):
- raise TypeError('atime and mtime must be numbers')
+ raise TypeError("atime and mtime must be numbers")
file_object.st_atime = times[0]
file_object.st_mtime = times[1]
elif ns is not None:
for file_time in ns:
if not isinstance(file_time, int):
- raise TypeError('atime and mtime must be ints')
+ raise TypeError("atime and mtime must be ints")
file_object.st_atime_ns = ns[0]
file_object.st_mtime_ns = ns[1]
else:
- current_time = now()
+ current_time = helpers.now()
file_object.st_atime = current_time
file_object.st_mtime = current_time
+ @staticmethod
def _handle_utime_arg_errors(
- self, ns: Optional[Tuple[int, int]],
- times: Optional[Tuple[Union[int, float], Union[int, float]]]):
+ ns: Optional[Tuple[int, int]],
+ times: Optional[Tuple[Union[int, float], Union[int, float]]],
+ ):
if times is not None and ns is not None:
raise ValueError(
- "utime: you may specify either 'times' or 'ns' but not both")
+ "utime: you may specify either 'times' or 'ns' but not both"
+ )
if times is not None and len(times) != 2:
- raise TypeError(
- "utime: 'times' must be either a tuple of two ints or None")
+ raise TypeError("utime: 'times' must be either a tuple of two ints or None")
if ns is not None and len(ns) != 2:
raise TypeError("utime: 'ns' must be a tuple of two ints")
- @Deprecator
- def SetIno(self, path, st_ino):
- """Set the self.st_ino attribute of file at 'path'.
- Note that a unique inode is assigned automatically to a new fake file.
- Using this function does not guarantee uniqueness and should used
- with caution.
-
- Args:
- path: Path to file.
- st_ino: The desired inode.
- """
- self.get_object(path).st_ino = st_ino
-
- def _add_open_file(
- self,
- file_obj: AnyFileWrapper) -> int:
+ def _add_open_file(self, file_obj: AnyFileWrapper) -> int:
"""Add file_obj to the list of open files on the filesystem.
Used internally to manage open files.
@@ -1415,7 +858,7 @@ class FakeFilesystem:
Open file object.
"""
if not is_int_type(file_des):
- raise TypeError('an integer is required')
+ raise TypeError("an integer is required")
valid = file_des < len(self.open_files)
if valid:
file_list = self.open_files[file_des]
@@ -1432,8 +875,9 @@ class FakeFilesystem:
Returns:
`True` if the file is open.
"""
- return (file_object in [wrappers[0].get_object()
- for wrappers in self.open_files if wrappers])
+ return file_object in [
+ wrappers[0].get_object() for wrappers in self.open_files if wrappers
+ ]
def _normalize_path_sep(self, path: AnyStr) -> AnyStr:
alt_sep = self._alternative_path_separator(path)
@@ -1482,16 +926,21 @@ class FakeFilesystem:
drive, path_str = self.splitdrive(path_str)
sep = self.get_path_separator(path_str)
is_absolute_path = path_str.startswith(sep)
- path_components: List[AnyStr] = path_str.split(sep)
- collapsed_path_components: List[AnyStr] = []
- dot = matching_string(path_str, '.')
- dotdot = matching_string(path_str, '..')
+ path_components: List[AnyStr] = path_str.split(
+ sep
+ ) # pytype: disable=invalid-annotation
+ collapsed_path_components: List[
+ AnyStr
+ ] = [] # pytype: disable=invalid-annotation
+ dot = matching_string(path_str, ".")
+ dotdot = matching_string(path_str, "..")
for component in path_components:
if (not component) or (component == dot):
continue
if component == dotdot:
if collapsed_path_components and (
- collapsed_path_components[-1] != dotdot):
+ collapsed_path_components[-1] != dotdot
+ ):
# Remove an up-reference: directory/..
collapsed_path_components.pop()
continue
@@ -1520,17 +969,21 @@ class FakeFilesystem:
def components_to_path():
if len(path_components) > len(normalized_components):
normalized_components.extend(
- to_string(p) for p in path_components[len(
- normalized_components):])
+ to_string(p) for p in path_components[len(normalized_components) :]
+ )
sep = self.path_separator
normalized_path = sep.join(normalized_components)
- if (self._starts_with_sep(path)
- and not self._starts_with_sep(normalized_path)):
+ if self.starts_with_sep(path) and not self.starts_with_sep(normalized_path):
normalized_path = sep + normalized_path
+ if len(normalized_path) == 2 and self.starts_with_drive_letter(
+ normalized_path
+ ):
+ normalized_path += sep
return normalized_path
if self.is_case_sensitive or not path:
return path
+ path = self.replace_windows_root(path)
path_components = self._path_components(path)
normalized_components = []
current_dir = self.root
@@ -1538,11 +991,13 @@ class FakeFilesystem:
if not isinstance(current_dir, FakeDirectory):
return components_to_path()
dir_name, directory = self._directory_content(
- current_dir, to_string(component))
+ current_dir, to_string(component)
+ )
if directory is None or (
- isinstance(directory, FakeDirectory) and
- directory._byte_contents is None and
- directory.st_size == 0):
+ isinstance(directory, FakeDirectory)
+ and directory._byte_contents is None
+ and directory.st_size == 0
+ ):
return components_to_path()
current_dir = cast(FakeDirectory, directory)
normalized_components.append(dir_name)
@@ -1564,17 +1019,18 @@ class FakeFilesystem:
path = self.normcase(path)
cwd = matching_string(path, self.cwd)
if not path:
- path = matching_string(path, self.path_separator)
- if path == matching_string(path, '.'):
+ path = self.get_path_separator(path)
+ if path == matching_string(path, "."):
path = cwd
elif not self._starts_with_root_path(path):
# Prefix relative paths with cwd, if cwd is not root.
root_name = matching_string(path, self.root.name)
- empty = matching_string(path, '')
+ empty = matching_string(path, "")
path = self.get_path_separator(path).join(
- (cwd != root_name and cwd or empty, path))
- if path == matching_string(path, '.'):
- path = cwd
+ (cwd != root_name and cwd or empty, path)
+ )
+ else:
+ path = self.replace_windows_root(path)
return self.normpath(path)
def splitpath(self, path: AnyStr) -> Tuple[AnyStr, AnyStr]:
@@ -1596,7 +1052,7 @@ class FakeFilesystem:
seps = sep if alt_sep is None else sep + alt_sep
drive, path = self.splitdrive(path)
i = len(path)
- while i and path[i-1] not in seps:
+ while i and path[i - 1] not in seps:
i -= 1
head, tail = path[:i], path[i:] # now tail has no slashes
# remove trailing slashes from head, unless it's all slashes
@@ -1623,8 +1079,7 @@ class FakeFilesystem:
norm_str = self.normcase(path_str)
sep = self.get_path_separator(path_str)
# UNC path_str handling
- if (norm_str[0:2] == sep * 2) and (
- norm_str[2:3] != sep):
+ if (norm_str[0:2] == sep * 2) and (norm_str[2:3] != sep):
# UNC path_str handling - splits off the mount point
# instead of the drive
sep_index = norm_str.find(sep, 2)
@@ -1636,12 +1091,67 @@ class FakeFilesystem:
if sep_index2 == -1:
sep_index2 = len(path_str)
return path_str[:sep_index2], path_str[sep_index2:]
- if path_str[1:2] == matching_string(path_str, ':'):
+ if path_str[1:2] == matching_string(path_str, ":"):
return path_str[:2], path_str[2:]
return path_str[:0], path_str
- def _join_paths_with_drive_support(
- self, *all_paths: AnyStr) -> AnyStr:
+ def splitroot(self, path: AnyStr):
+ """Split a pathname into drive, root and tail.
+ Implementation taken from ntpath and posixpath.
+ """
+ p = os.fspath(path)
+ if isinstance(p, bytes):
+ sep = self.path_separator.encode()
+ altsep = None
+ if self.alternative_path_separator:
+ altsep = self.alternative_path_separator.encode()
+ colon = b":"
+ unc_prefix = b"\\\\?\\UNC\\"
+ empty = b""
+ else:
+ sep = self.path_separator
+ altsep = self.alternative_path_separator
+ colon = ":"
+ unc_prefix = "\\\\?\\UNC\\"
+ empty = ""
+ if self.is_windows_fs:
+ normp = p.replace(altsep, sep) if altsep else p
+ if normp[:1] == sep:
+ if normp[1:2] == sep:
+ # UNC drives, e.g. \\server\share or \\?\UNC\server\share
+ # Device drives, e.g. \\.\device or \\?\device
+ start = 8 if normp[:8].upper() == unc_prefix else 2
+ index = normp.find(sep, start)
+ if index == -1:
+ return p, empty, empty
+ index2 = normp.find(sep, index + 1)
+ if index2 == -1:
+ return p, empty, empty
+ return p[:index2], p[index2 : index2 + 1], p[index2 + 1 :]
+ else:
+ # Relative path with root, e.g. \Windows
+ return empty, p[:1], p[1:]
+ elif normp[1:2] == colon:
+ if normp[2:3] == sep:
+ # Absolute drive-letter path, e.g. X:\Windows
+ return p[:2], p[2:3], p[3:]
+ else:
+ # Relative path with drive, e.g. X:Windows
+ return p[:2], empty, p[2:]
+ else:
+ # Relative path, e.g. Windows
+ return empty, empty, p
+ else:
+ if p[:1] != sep:
+ # Relative path, e.g.: 'foo'
+ return empty, empty, p
+ elif p[1:2] != sep or p[2:3] == sep:
+ # Absolute path, e.g.: '/foo', '///foo', '////foo', etc.
+ return empty, sep, p[1:]
+ else:
+ return empty, p[:2], p[2:]
+
+ def _join_paths_with_drive_support(self, *all_paths: AnyStr) -> AnyStr:
"""Taken from Python 3.5 os.path.join() code in ntpath.py
and slightly adapted"""
base_path = all_paths[0]
@@ -1658,8 +1168,7 @@ class FakeFilesystem:
result_path = path_part
continue
elif drive_part and drive_part != result_drive:
- if (self.is_case_sensitive or
- drive_part.lower() != result_drive.lower()):
+ if self.is_case_sensitive or drive_part.lower() != result_drive.lower():
# Different drives => ignore the first path entirely
result_drive = drive_part
result_path = path_part
@@ -1671,9 +1180,13 @@ class FakeFilesystem:
result_path = result_path + sep
result_path = result_path + path_part
# add separator between UNC and non-absolute path
- colon = matching_string(base_path, ':')
- if (result_path and result_path[:1] not in seps and
- result_drive and result_drive[-1:] != colon):
+ colon = matching_string(base_path, ":")
+ if (
+ result_path
+ and result_path[:1] not in seps
+ and result_drive
+ and result_drive[-1:] != colon
+ ):
return result_drive + sep + result_path
return result_drive + result_path
@@ -1699,18 +1212,19 @@ class FakeFilesystem:
# An absolute path
joined_path_segments = [path_segment]
else:
- if (joined_path_segments and
- not joined_path_segments[-1].endswith(sep)):
+ if joined_path_segments and not joined_path_segments[-1].endswith(sep):
joined_path_segments.append(sep)
if path_segment:
joined_path_segments.append(path_segment)
- return matching_string(file_paths[0], '').join(joined_path_segments)
+ return matching_string(file_paths[0], "").join(joined_path_segments)
@overload
- def _path_components(self, path: str) -> List[str]: ...
+ def _path_components(self, path: str) -> List[str]:
+ ...
@overload
- def _path_components(self, path: bytes) -> List[bytes]: ...
+ def _path_components(self, path: bytes) -> List[bytes]:
+ ...
def _path_components(self, path: AnyStr) -> List[AnyStr]:
"""Breaks the path into a list of component names.
@@ -1751,7 +1265,7 @@ class FakeFilesystem:
path_components.insert(0, drive)
return path_components
- def _starts_with_drive_letter(self, file_path: AnyStr) -> bool:
+ def starts_with_drive_letter(self, file_path: AnyStr) -> bool:
"""Return True if file_path starts with a drive letter.
Args:
@@ -1761,12 +1275,11 @@ class FakeFilesystem:
`True` if drive letter support is enabled in the filesystem and
the path starts with a drive letter.
"""
- colon = matching_string(file_path, ':')
- if (len(file_path) >= 2 and
- file_path[:1].isalpha and file_path[1:2] == colon):
+ colon = matching_string(file_path, ":")
+ if len(file_path) >= 2 and file_path[0:1].isalpha() and file_path[1:2] == colon:
if self.is_windows_fs:
return True
- if os.name == 'nt':
+ if os.name == "nt":
# special case if we are emulating Posix under Windows
# check if the path exists because it has been mapped in
# this is not foolproof, but handles most cases
@@ -1780,17 +1293,55 @@ class FakeFilesystem:
def _starts_with_root_path(self, file_path: AnyStr) -> bool:
root_name = matching_string(file_path, self.root.name)
file_path = self._normalize_path_sep(file_path)
- return (file_path.startswith(root_name) or
- not self.is_case_sensitive and file_path.lower().startswith(
- root_name.lower()) or
- self._starts_with_drive_letter(file_path))
+ return (
+ file_path.startswith(root_name)
+ or not self.is_case_sensitive
+ and file_path.lower().startswith(root_name.lower())
+ or self.starts_with_drive_letter(file_path)
+ )
+
+ def replace_windows_root(self, path: AnyStr) -> AnyStr:
+ """In windows, if a path starts with a single separator,
+ it points to the root dir of the current mount point, usually a
+ drive - replace it with that mount point path to get the real path.
+ """
+ if path and self.is_windows_fs and self.root_dir:
+ sep = self.get_path_separator(path)
+ # ignore UNC paths
+ if path[0:1] == sep and (len(path) == 1 or path[1:2] != sep):
+ # check if we already have a mount point for that path
+ for root_path in self.mount_points:
+ root_path = matching_string(path, root_path)
+ if path.startswith(root_path):
+ return path
+ # must be a pointer to the current drive - replace it
+ mount_point = matching_string(path, self.root_dir_name)
+ path = mount_point + path[1:]
+ return path
def _is_root_path(self, file_path: AnyStr) -> bool:
root_name = matching_string(file_path, self.root.name)
- return (file_path == root_name or not self.is_case_sensitive and
- file_path.lower() == root_name.lower() or
- 2 <= len(file_path) <= 3 and
- self._starts_with_drive_letter(file_path))
+ return file_path == root_name or self.is_mount_point(file_path)
+
+ def is_mount_point(self, file_path: AnyStr) -> bool:
+ """Return `True` if `file_path` points to a mount point."""
+ for mount_point in self.mount_points:
+ mount_point = matching_string(file_path, mount_point)
+ if (
+ file_path == mount_point
+ or not self.is_case_sensitive
+ and file_path.lower() == mount_point.lower()
+ ):
+ return True
+ if (
+ self.is_windows_fs
+ and len(file_path) == 3
+ and len(mount_point) == 2
+ and self.starts_with_drive_letter(file_path)
+ and file_path[:2].lower() == mount_point.lower()
+ ):
+ return True
+ return False
def ends_with_path_separator(self, path: Union[int, AnyPath]) -> bool:
"""Return True if ``file_path`` ends with a valid path separator."""
@@ -1801,26 +1352,28 @@ class FakeFilesystem:
return False
sep = self.get_path_separator(file_path)
altsep = self._alternative_path_separator(file_path)
- return (file_path not in (sep, altsep) and
- (file_path.endswith(sep) or
- altsep is not None and file_path.endswith(altsep)))
+ return file_path not in (sep, altsep) and (
+ file_path.endswith(sep) or altsep is not None and file_path.endswith(altsep)
+ )
def is_filepath_ending_with_separator(self, path: AnyStr) -> bool:
if not self.ends_with_path_separator(path):
return False
return self.isfile(self._path_without_trailing_separators(path))
- def _directory_content(self, directory: FakeDirectory,
- component: str) -> Tuple[Optional[str],
- Optional[AnyFile]]:
+ def _directory_content(
+ self, directory: FakeDirectory, component: str
+ ) -> Tuple[Optional[str], Optional[AnyFile]]:
if not isinstance(directory, FakeDirectory):
return None, None
if component in directory.entries:
return component, directory.entries[component]
if not self.is_case_sensitive:
- matching_content = [(subdir, directory.entries[subdir]) for
- subdir in directory.entries
- if subdir.lower() == component.lower()]
+ matching_content = [
+ (subdir, directory.entries[subdir])
+ for subdir in directory.entries
+ if subdir.lower() == component.lower()
+ ]
if matching_content:
return matching_content[0]
@@ -1841,7 +1394,7 @@ class FakeFilesystem:
"""
if check_link and self.islink(file_path):
return True
- path = to_string(make_string_path(file_path))
+ path = to_string(self.make_string_path(file_path))
if path is None:
raise TypeError
if not path:
@@ -1854,21 +1407,19 @@ class FakeFilesystem:
path = self.resolve_path(path)
except OSError:
return False
- if path == self.root.name:
+ if self._is_root_path(path):
return True
path_components: List[str] = self._path_components(path)
current_dir = self.root
for component in path_components:
- directory = self._directory_content(
- current_dir, to_string(component))[1]
+ directory = self._directory_content(current_dir, to_string(component))[1]
if directory is None:
return False
current_dir = cast(FakeDirectory, directory)
return True
- def resolve_path(self,
- file_path: AnyStr, allow_fd: bool = False) -> AnyStr:
+ def resolve_path(self, file_path: AnyStr, allow_fd: bool = False) -> AnyStr:
"""Follow a path, resolving symlinks.
ResolvePath traverses the filesystem along the specified file path,
@@ -1911,23 +1462,29 @@ class FakeFilesystem:
path = make_string_path(file_path)
if path is None:
# file.open(None) raises TypeError, so mimic that.
- raise TypeError('Expected file system path string, received None')
+ raise TypeError("Expected file system path string, received None")
if not path or not self._valid_relative_path(path):
# file.open('') raises OSError, so mimic that, and validate that
# all parts of a relative path exist.
self.raise_os_error(errno.ENOENT, path)
path = self.absnormpath(self._original_path(path))
+ path = self.replace_windows_root(path)
if self._is_root_path(path):
return path
if path == matching_string(path, self.dev_null.name):
return path
path_components = self._path_components(path)
resolved_components = self._resolve_components(path_components)
- return self._components_to_path(resolved_components)
+ path = self._components_to_path(resolved_components)
+ # after resolving links, we have to check again for Windows root
+ return self.replace_windows_root(path) # pytype: disable=bad-return-type
def _components_to_path(self, component_folders):
- sep = (self.get_path_separator(component_folders[0])
- if component_folders else self.path_separator)
+ sep = (
+ self.get_path_separator(component_folders[0])
+ if component_folders
+ else self.path_separator
+ )
path = sep.join(component_folders)
if not self._starts_with_root_path(path):
path = sep + path
@@ -1957,9 +1514,10 @@ class FakeFilesystem:
# check. It is just a quick hack to prevent us from looping
# forever on cycles.
if link_depth > _MAX_LINK_DEPTH:
- self.raise_os_error(errno.ELOOP,
- self._components_to_path(
- resolved_components))
+ self.raise_os_error(
+ errno.ELOOP,
+ self._components_to_path(resolved_components),
+ )
link_path = self._follow_link(resolved_components, directory)
# Following the link might result in the complete replacement
@@ -1976,16 +1534,14 @@ class FakeFilesystem:
def _valid_relative_path(self, file_path: AnyStr) -> bool:
if self.is_windows_fs:
return True
- slash_dotdot = matching_string(
- file_path, self.path_separator + '..')
+ slash_dotdot = matching_string(file_path, self.path_separator + "..")
while file_path and slash_dotdot in file_path:
- file_path = file_path[:file_path.rfind(slash_dotdot)]
+ file_path = file_path[: file_path.rfind(slash_dotdot)]
if not self.exists(self.absnormpath(file_path)):
return False
return True
- def _follow_link(self, link_path_components: List[str],
- link: AnyFile) -> str:
+ def _follow_link(self, link_path_components: List[str], link: AnyFile) -> str:
"""Follow a link w.r.t. a path resolved so far.
The component is either a real file, which is a no-op, or a
@@ -2011,7 +1567,7 @@ class FakeFilesystem:
link_path = link.contents
if link_path is not None:
# ignore UNC prefix for local files
- if self.is_windows_fs and link_path.startswith('\\\\?\\'):
+ if self.is_windows_fs and link_path.startswith("\\\\?\\"):
link_path = link_path[4:]
sep = self.get_path_separator(link_path)
# For links to absolute paths, we want to throw out everything
@@ -2028,12 +1584,15 @@ class FakeFilesystem:
link_path = sep.join(components)
# Don't call self.NormalizePath(), as we don't want to prepend
# self.cwd.
- return self.normpath(link_path)
+ return self.normpath(link_path) # pytype: disable=bad-return-type
raise ValueError("Invalid link")
- def get_object_from_normpath(self,
- file_path: AnyPath,
- check_read_perm: bool = True) -> AnyFile:
+ def get_object_from_normpath(
+ self,
+ file_path: AnyPath,
+ check_read_perm: bool = True,
+ check_owner: bool = False,
+ ) -> AnyFile:
"""Search for the specified filesystem object within the fake
filesystem.
@@ -2042,6 +1601,9 @@ class FakeFilesystem:
path that has already been normalized/resolved.
check_read_perm: If True, raises OSError if a parent directory
does not have read permission
+ check_owner: If True, and check_read_perm is also True,
+ only checks read permission if the current user id is
+ different from the file object user id
Returns:
The FakeFile object corresponding to file_path.
@@ -2062,22 +1624,34 @@ class FakeFilesystem:
for component in path_components:
if S_ISLNK(target.st_mode):
if target.contents:
- target = cast(FakeDirectory,
- self.resolve(target.contents))
+ target = cast(FakeDirectory, self.resolve(target.contents))
if not S_ISDIR(target.st_mode):
if not self.is_windows_fs:
self.raise_os_error(errno.ENOTDIR, path)
self.raise_os_error(errno.ENOENT, path)
target = target.get_entry(component) # type: ignore
- if (not is_root() and check_read_perm and target and
- not target.st_mode & PERM_READ):
+ if (
+ not is_root()
+ and check_read_perm
+ and target
+ and not self._can_read(target, check_owner)
+ ):
self.raise_os_error(errno.EACCES, target.path)
except KeyError:
self.raise_os_error(errno.ENOENT, path)
return target
- def get_object(self, file_path: AnyPath,
- check_read_perm: bool = True) -> FakeFile:
+ @staticmethod
+ def _can_read(target, owner_can_read):
+ if target.st_uid == helpers.get_uid():
+ if owner_can_read or target.st_mode & 0o400:
+ return True
+ if target.st_gid == get_gid():
+ if target.st_mode & 0o040:
+ return True
+ return target.st_mode & 0o004
+
+ def get_object(self, file_path: AnyPath, check_read_perm: bool = True) -> FakeFile:
"""Search for the specified filesystem object within the fake
filesystem.
@@ -2096,10 +1670,14 @@ class FakeFilesystem:
path = self.absnormpath(self._original_path(path))
return self.get_object_from_normpath(path, check_read_perm)
- def resolve(self, file_path: AnyStr,
- follow_symlinks: bool = True,
- allow_fd: bool = False,
- check_read_perm: bool = True) -> FakeFile:
+ def resolve(
+ self,
+ file_path: AnyStr,
+ follow_symlinks: bool = True,
+ allow_fd: bool = False,
+ check_read_perm: bool = True,
+ check_owner: bool = False,
+ ) -> FakeFile:
"""Search for the specified filesystem object, resolving all links.
Args:
@@ -2109,6 +1687,9 @@ class FakeFilesystem:
allow_fd: If `True`, `file_path` may be an open file descriptor
check_read_perm: If True, raises OSError if a parent directory
does not have read permission
+ check_owner: If True, and check_read_perm is also True,
+ only checks read permission if the current user id is
+ different from the file object user id
Returns:
The FakeFile object corresponding to `file_path`.
@@ -2119,12 +1700,14 @@ class FakeFilesystem:
if isinstance(file_path, int):
if allow_fd:
return self.get_open_file(file_path).get_object()
- raise TypeError('path should be string, bytes or '
- 'os.PathLike, not int')
+ raise TypeError("path should be string, bytes or " "os.PathLike, not int")
if follow_symlinks:
- return self.get_object_from_normpath(self.resolve_path(
- file_path, check_read_perm), check_read_perm)
+ return self.get_object_from_normpath(
+ self.resolve_path(file_path, allow_fd),
+ check_read_perm,
+ check_owner,
+ )
return self.lresolve(file_path)
def lresolve(self, path: AnyPath) -> FakeFile:
@@ -2151,7 +1734,7 @@ class FakeFilesystem:
# remove trailing separator
path_str = self._path_without_trailing_separators(path_str)
- if path_str == matching_string(path_str, '.'):
+ if path_str == matching_string(path_str, "."):
path_str = matching_string(path_str, self.cwd)
path_str = self._original_path(path_str)
@@ -2165,12 +1748,16 @@ class FakeFilesystem:
if not self.is_windows_fs and isinstance(parent_obj, FakeFile):
self.raise_os_error(errno.ENOTDIR, path_str)
self.raise_os_error(errno.ENOENT, path_str)
- if not parent_obj.st_mode & PERM_READ:
+ if not parent_obj.st_mode & helpers.PERM_READ:
self.raise_os_error(errno.EACCES, parent_directory)
- return (parent_obj.get_entry(to_string(child_name)) if child_name
- else parent_obj)
+ return (
+ parent_obj.get_entry(to_string(child_name))
+ if child_name
+ else parent_obj
+ )
except KeyError:
- self.raise_os_error(errno.ENOENT, path_str)
+ pass
+ raise OSError(errno.ENOENT, path_str)
def add_object(self, file_path: AnyStr, file_object: AnyFile) -> None:
"""Add a fake file or directory into the filesystem at file_path.
@@ -2184,7 +1771,7 @@ class FakeFilesystem:
directory.
"""
if not file_path:
- target_directory = self.root
+ target_directory = self.root_dir
else:
target_directory = cast(FakeDirectory, self.resolve(file_path))
if not S_ISDIR(target_directory.st_mode):
@@ -2192,9 +1779,12 @@ class FakeFilesystem:
self.raise_os_error(error, file_path)
target_directory.add_entry(file_object)
- def rename(self, old_file_path: AnyPath,
- new_file_path: AnyPath,
- force_replace: bool = False) -> None:
+ def rename(
+ self,
+ old_file_path: AnyPath,
+ new_file_path: AnyPath,
+ force_replace: bool = False,
+ ) -> None:
"""Renames a FakeFile object at old_file_path to new_file_path,
preserving all properties.
@@ -2231,13 +1821,12 @@ class FakeFilesystem:
old_object = self.lresolve(old_path)
if not self.is_windows_fs:
- self._handle_posix_dir_link_errors(
- new_path, old_path, ends_with_sep)
+ self._handle_posix_dir_link_errors(new_path, old_path, ends_with_sep)
if self.exists(new_path, check_link=True):
renamed_path = self._rename_to_existing_path(
- force_replace, new_path, old_path,
- old_object, ends_with_sep)
+ force_replace, new_path, old_path, old_object, ends_with_sep
+ )
if renamed_path is None:
return
@@ -2254,8 +1843,8 @@ class FakeFilesystem:
self.raise_os_error(errno.EXDEV, old_path)
if not S_ISDIR(new_dir_object.st_mode):
self.raise_os_error(
- errno.EACCES if self.is_windows_fs else errno.ENOTDIR,
- new_path)
+ errno.EACCES if self.is_windows_fs else errno.ENOTDIR, new_path
+ )
if new_dir_object.has_parent_object(old_object):
self.raise_os_error(errno.EINVAL, new_path)
@@ -2266,8 +1855,11 @@ class FakeFilesystem:
old_dir_object.remove_entry(old_name, recursive=False)
object_to_rename.name = new_name
new_name = new_dir_object._normalized_entryname(new_name)
- old_entry = (new_dir_object.get_entry(new_name)
- if new_name in new_dir_object.entries else None)
+ old_entry = (
+ new_dir_object.get_entry(new_name)
+ if new_name in new_dir_object.entries
+ else None
+ )
try:
if old_entry:
# in case of overwriting remove the old entry first
@@ -2285,31 +1877,45 @@ class FakeFilesystem:
# note that the check for trailing sep has to be done earlier
if self.islink(path):
if not self.exists(path):
- error = (errno.ENOENT if self.is_macos else
- errno.EINVAL if self.is_windows_fs else errno.ENOTDIR)
+ error = (
+ errno.ENOENT
+ if self.is_macos
+ else errno.EINVAL
+ if self.is_windows_fs
+ else errno.ENOTDIR
+ )
self.raise_os_error(error, path)
- def _handle_posix_dir_link_errors(self, new_file_path: AnyStr,
- old_file_path: AnyStr,
- ends_with_sep: bool) -> None:
- if (self.isdir(old_file_path, follow_symlinks=False) and
- self.islink(new_file_path)):
+ def _handle_posix_dir_link_errors(
+ self, new_file_path: AnyStr, old_file_path: AnyStr, ends_with_sep: bool
+ ) -> None:
+ if self.isdir(old_file_path, follow_symlinks=False) and self.islink(
+ new_file_path
+ ):
self.raise_os_error(errno.ENOTDIR, new_file_path)
- if (self.isdir(new_file_path, follow_symlinks=False) and
- self.islink(old_file_path)):
+ if self.isdir(new_file_path, follow_symlinks=False) and self.islink(
+ old_file_path
+ ):
if ends_with_sep and self.is_macos:
return
error = errno.ENOTDIR if ends_with_sep else errno.EISDIR
self.raise_os_error(error, new_file_path)
- if (ends_with_sep and self.islink(old_file_path) and
- old_file_path == new_file_path and not self.is_windows_fs):
+ if (
+ ends_with_sep
+ and self.islink(old_file_path)
+ and old_file_path == new_file_path
+ and not self.is_windows_fs
+ ):
self.raise_os_error(errno.ENOTDIR, new_file_path)
- def _rename_to_existing_path(self, force_replace: bool,
- new_file_path: AnyStr,
- old_file_path: AnyStr,
- old_object: FakeFile,
- ends_with_sep: bool) -> Optional[AnyStr]:
+ def _rename_to_existing_path(
+ self,
+ force_replace: bool,
+ new_file_path: AnyStr,
+ old_file_path: AnyStr,
+ old_object: FakeFile,
+ ends_with_sep: bool,
+ ) -> Optional[AnyStr]:
new_object = self.get_object(new_file_path)
if old_file_path == new_file_path:
if not S_ISLNK(new_object.st_mode) and ends_with_sep:
@@ -2321,8 +1927,12 @@ class FakeFilesystem:
return self._rename_same_object(new_file_path, old_file_path)
if S_ISDIR(new_object.st_mode) or S_ISLNK(new_object.st_mode):
self._handle_rename_error_for_dir_or_link(
- force_replace, new_file_path,
- new_object, old_object, ends_with_sep)
+ force_replace,
+ new_file_path,
+ new_object,
+ old_object,
+ ends_with_sep,
+ )
elif S_ISDIR(old_object.st_mode):
error = errno.EEXIST if self.is_windows_fs else errno.ENOTDIR
self.raise_os_error(error, new_file_path)
@@ -2332,11 +1942,14 @@ class FakeFilesystem:
self.remove_object(new_file_path)
return new_file_path
- def _handle_rename_error_for_dir_or_link(self, force_replace: bool,
- new_file_path: AnyStr,
- new_object: FakeFile,
- old_object: FakeFile,
- ends_with_sep: bool) -> None:
+ def _handle_rename_error_for_dir_or_link(
+ self,
+ force_replace: bool,
+ new_file_path: AnyStr,
+ new_object: FakeFile,
+ old_object: FakeFile,
+ ends_with_sep: bool,
+ ) -> None:
if self.is_windows_fs:
if force_replace:
self.raise_os_error(errno.EACCES, new_file_path)
@@ -2344,37 +1957,41 @@ class FakeFilesystem:
self.raise_os_error(errno.EEXIST, new_file_path)
if not S_ISLNK(new_object.st_mode):
if new_object.entries:
- if (not S_ISLNK(old_object.st_mode) or
- not ends_with_sep or not self.is_macos):
+ if (
+ not S_ISLNK(old_object.st_mode)
+ or not ends_with_sep
+ or not self.is_macos
+ ):
self.raise_os_error(errno.ENOTEMPTY, new_file_path)
if S_ISREG(old_object.st_mode):
self.raise_os_error(errno.EISDIR, new_file_path)
- def _rename_same_object(self, new_file_path: AnyStr,
- old_file_path: AnyStr) -> Optional[AnyStr]:
+ def _rename_same_object(
+ self, new_file_path: AnyStr, old_file_path: AnyStr
+ ) -> Optional[AnyStr]:
do_rename = old_file_path.lower() == new_file_path.lower()
if not do_rename:
try:
real_old_path = self.resolve_path(old_file_path)
original_old_path = self._original_path(real_old_path)
real_new_path = self.resolve_path(new_file_path)
- if (real_new_path == original_old_path and
- (new_file_path == real_old_path) ==
- (new_file_path.lower() ==
- real_old_path.lower())):
- real_object = self.resolve(old_file_path,
- follow_symlinks=False)
- do_rename = (os.path.basename(old_file_path) ==
- real_object.name or not self.is_macos)
+ if real_new_path == original_old_path and (
+ new_file_path == real_old_path
+ ) == (new_file_path.lower() == real_old_path.lower()):
+ real_object = self.resolve(old_file_path, follow_symlinks=False)
+ do_rename = (
+ os.path.basename(old_file_path) == real_object.name
+ or not self.is_macos
+ )
else:
- do_rename = (real_new_path.lower() ==
- real_old_path.lower())
+ do_rename = real_new_path.lower() == real_old_path.lower()
if do_rename:
# only case is changed in case-insensitive file
# system - do the rename
parent, file_name = self.splitpath(new_file_path)
new_file_path = self.joinpaths(
- self._original_path(parent), file_name)
+ self._original_path(parent), file_name
+ )
except OSError:
# ResolvePath may fail due to symlink loop issues or
# similar - in this case just assume the paths
@@ -2411,11 +2028,12 @@ class FakeFilesystem:
def make_string_path(self, path: AnyPath) -> AnyStr:
path_str = make_string_path(path)
os_sep = matching_string(path_str, os.sep)
- fake_sep = matching_string(path_str, self.path_separator)
+ fake_sep = self.get_path_separator(path_str)
return path_str.replace(os_sep, fake_sep) # type: ignore[return-value]
- def create_dir(self, directory_path: AnyPath,
- perm_bits: int = PERM_DEF) -> FakeDirectory:
+ def create_dir(
+ self, directory_path: AnyPath, perm_bits: int = helpers.PERM_DEF
+ ) -> FakeDirectory:
"""Create `directory_path`, and all the parent directories.
Helper method to set up your test faster.
@@ -2433,19 +2051,19 @@ class FakeFilesystem:
dir_path = self.make_string_path(directory_path)
dir_path = self.absnormpath(dir_path)
self._auto_mount_drive_if_needed(dir_path)
- if (self.exists(dir_path, check_link=True) and
- dir_path not in self.mount_points):
+ if self.exists(dir_path, check_link=True) and dir_path not in self.mount_points:
self.raise_os_error(errno.EEXIST, dir_path)
path_components = self._path_components(dir_path)
current_dir = self.root
new_dirs = []
for component in [to_string(p) for p in path_components]:
- directory = self._directory_content(
- current_dir, to_string(component))[1]
+ directory = self._directory_content(current_dir, to_string(component))[1]
if not directory:
new_dir = FakeDirectory(component, filesystem=self)
new_dirs.append(new_dir)
+ if self.is_windows_fs and current_dir == self.root:
+ current_dir = self.root_dir
current_dir.add_entry(new_dir)
current_dir = new_dir
else:
@@ -2464,15 +2082,18 @@ class FakeFilesystem:
return current_dir
- def create_file(self, file_path: AnyPath,
- st_mode: int = S_IFREG | PERM_DEF_FILE,
- contents: AnyString = '',
- st_size: Optional[int] = None,
- create_missing_dirs: bool = True,
- apply_umask: bool = False,
- encoding: Optional[str] = None,
- errors: Optional[str] = None,
- side_effect: Optional[Callable] = None) -> FakeFile:
+ def create_file(
+ self,
+ file_path: AnyPath,
+ st_mode: int = S_IFREG | helpers.PERM_DEF_FILE,
+ contents: AnyString = "",
+ st_size: Optional[int] = None,
+ create_missing_dirs: bool = True,
+ apply_umask: bool = False,
+ encoding: Optional[str] = None,
+ errors: Optional[str] = None,
+ side_effect: Optional[Callable] = None,
+ ) -> FakeFile:
"""Create `file_path`, including all the parent directories along
the way.
@@ -2503,12 +2124,23 @@ class FakeFilesystem:
OSError: if the containing directory is required and missing.
"""
return self.create_file_internally(
- file_path, st_mode, contents, st_size, create_missing_dirs,
- apply_umask, encoding, errors, side_effect=side_effect)
+ file_path,
+ st_mode,
+ contents,
+ st_size,
+ create_missing_dirs,
+ apply_umask,
+ encoding,
+ errors,
+ side_effect=side_effect,
+ )
- def add_real_file(self, source_path: AnyPath,
- read_only: bool = True,
- target_path: Optional[AnyPath] = None) -> FakeFile:
+ def add_real_file(
+ self,
+ source_path: AnyPath,
+ read_only: bool = True,
+ target_path: Optional[AnyPath] = None,
+ ) -> FakeFile:
"""Create `file_path`, including all the parent directories along the
way, for an existing real file. The contents of the real file are read
only on demand.
@@ -2536,20 +2168,19 @@ class FakeFilesystem:
target_path = target_path or source_path
source_path_str = make_string_path(source_path)
real_stat = os.stat(source_path_str)
- fake_file = self.create_file_internally(target_path,
- read_from_real_fs=True)
+ fake_file = self.create_file_internally(target_path, read_from_real_fs=True)
# for read-only mode, remove the write/executable permission bits
fake_file.stat_result.set_from_stat_result(real_stat)
if read_only:
fake_file.st_mode &= 0o777444
fake_file.file_path = source_path_str
- self.change_disk_usage(fake_file.size, fake_file.name,
- fake_file.st_dev)
+ self.change_disk_usage(fake_file.size, fake_file.name, fake_file.st_dev)
return fake_file
- def add_real_symlink(self, source_path: AnyPath,
- target_path: Optional[AnyPath] = None) -> FakeFile:
+ def add_real_symlink(
+ self, source_path: AnyPath, target_path: Optional[AnyPath] = None
+ ) -> FakeFile:
"""Create a symlink at source_path (or target_path, if given). It will
point to the same path as the symlink on the real filesystem. Relative
symlinks will point relative to their new location. Absolute symlinks
@@ -2570,10 +2201,8 @@ class FakeFilesystem:
OSError: if the directory already exists in the fake file system.
"""
source_path_str = make_string_path(source_path) # TODO: add test
- source_path_str = self._path_without_trailing_separators(
- source_path_str)
- if (not os.path.exists(source_path_str) and
- not os.path.islink(source_path_str)):
+ source_path_str = self._path_without_trailing_separators(source_path_str)
+ if not os.path.exists(source_path_str) and not os.path.islink(source_path_str):
self.raise_os_error(errno.ENOENT, source_path_str)
target = os.readlink(source_path_str)
@@ -2584,10 +2213,12 @@ class FakeFilesystem:
return self.create_symlink(source_path_str, target)
def add_real_directory(
- self, source_path: AnyPath,
- read_only: bool = True,
- lazy_read: bool = True,
- target_path: Optional[AnyPath] = None) -> FakeDirectory:
+ self,
+ source_path: AnyPath,
+ read_only: bool = True,
+ lazy_read: bool = True,
+ target_path: Optional[AnyPath] = None,
+ ) -> FakeDirectory:
"""Create a fake directory corresponding to the real directory at the
specified path. Add entries in the fake directory corresponding to
the entries in the real directory. Symlinks are supported.
@@ -2616,26 +2247,29 @@ class FakeFilesystem:
OSError: if the directory already exists in the fake file system.
"""
source_path_str = make_string_path(source_path) # TODO: add test
- source_path_str = self._path_without_trailing_separators(
- source_path_str)
+ source_path_str = self._path_without_trailing_separators(source_path_str)
if not os.path.exists(source_path_str):
self.raise_os_error(errno.ENOENT, source_path_str)
- target_path = target_path or source_path_str
+ target_path_str = make_string_path(target_path or source_path_str)
+ self._auto_mount_drive_if_needed(target_path_str)
new_dir: FakeDirectory
if lazy_read:
- parent_path = os.path.split(target_path)[0]
+ parent_path = os.path.split(target_path_str)[0]
if self.exists(parent_path):
parent_dir = self.get_object(parent_path)
else:
parent_dir = self.create_dir(parent_path)
new_dir = FakeDirectoryFromRealDirectory(
- source_path_str, self, read_only, target_path)
+ source_path_str, self, read_only, target_path_str
+ )
parent_dir.add_entry(new_dir)
else:
- new_dir = self.create_dir(target_path)
+ new_dir = self.create_dir(target_path_str)
for base, _, files in os.walk(source_path_str):
- new_base = os.path.join(new_dir.path, # type: ignore[arg-type]
- os.path.relpath(base, source_path_str))
+ new_base = os.path.join(
+ new_dir.path, # type: ignore[arg-type]
+ os.path.relpath(base, source_path_str),
+ )
for fileEntry in os.listdir(base):
abs_fileEntry = os.path.join(base, fileEntry)
@@ -2643,19 +2277,23 @@ class FakeFilesystem:
continue
self.add_real_symlink(
- abs_fileEntry, os.path.join(new_base, fileEntry))
+ abs_fileEntry, os.path.join(new_base, fileEntry)
+ )
for fileEntry in files:
path = os.path.join(base, fileEntry)
if os.path.islink(path):
continue
- self.add_real_file(path,
- read_only,
- os.path.join(new_base, fileEntry))
+ self.add_real_file(
+ path, read_only, os.path.join(new_base, fileEntry)
+ )
return new_dir
- def add_real_paths(self, path_list: List[AnyStr],
- read_only: bool = True,
- lazy_dir_read: bool = True) -> None:
+ def add_real_paths(
+ self,
+ path_list: List[AnyStr],
+ read_only: bool = True,
+ lazy_dir_read: bool = True,
+ ) -> None:
"""This convenience method adds multiple files and/or directories from
the real file system to the fake file system. See `add_real_file()` and
`add_real_directory()`.
@@ -2683,16 +2321,18 @@ class FakeFilesystem:
self.add_real_file(path, read_only)
def create_file_internally(
- self, file_path: AnyPath,
- st_mode: int = S_IFREG | PERM_DEF_FILE,
- contents: AnyString = '',
- st_size: Optional[int] = None,
- create_missing_dirs: bool = True,
- apply_umask: bool = False,
- encoding: Optional[str] = None,
- errors: Optional[str] = None,
- read_from_real_fs: bool = False,
- side_effect: Optional[Callable] = None) -> FakeFile:
+ self,
+ file_path: AnyPath,
+ st_mode: int = S_IFREG | helpers.PERM_DEF_FILE,
+ contents: AnyString = "",
+ st_size: Optional[int] = None,
+ create_missing_dirs: bool = True,
+ apply_umask: bool = False,
+ encoding: Optional[str] = None,
+ errors: Optional[str] = None,
+ read_from_real_fs: bool = False,
+ side_effect: Optional[Callable] = None,
+ ) -> FakeFile:
"""Internal fake file creator that supports both normal fake files
and fake files based on real files.
@@ -2719,7 +2359,8 @@ class FakeFilesystem:
path = self.absnormpath(path)
if not is_int_type(st_mode):
raise TypeError(
- 'st_mode must be of int type - did you mean to set contents?')
+ "st_mode must be of int type - did you mean to set contents?"
+ )
if self.exists(path, check_link=True):
self.raise_os_error(errno.EEXIST, path)
@@ -2730,27 +2371,33 @@ class FakeFilesystem:
if not self.exists(parent_directory):
if not create_missing_dirs:
self.raise_os_error(errno.ENOENT, parent_directory)
- self.create_dir(parent_directory)
+ parent_directory = matching_string(
+ path, self.create_dir(parent_directory).path # type: ignore
+ )
else:
parent_directory = self._original_path(parent_directory)
if apply_umask:
st_mode &= ~self.umask
file_object: FakeFile
if read_from_real_fs:
- file_object = FakeFileFromRealFile(to_string(path),
- filesystem=self,
- side_effect=side_effect)
+ file_object = FakeFileFromRealFile(
+ to_string(path), filesystem=self, side_effect=side_effect
+ )
else:
- file_object = FakeFile(new_file, st_mode, filesystem=self,
- encoding=encoding, errors=errors,
- side_effect=side_effect)
+ file_object = FakeFile(
+ new_file,
+ st_mode,
+ filesystem=self,
+ encoding=encoding,
+ errors=errors,
+ side_effect=side_effect,
+ )
self.add_object(parent_directory, file_object)
if st_size is None and contents is None:
- contents = ''
- if (not read_from_real_fs and
- (contents is not None or st_size is not None)):
+ contents = ""
+ if not read_from_real_fs and (contents is not None or st_size is not None):
try:
if st_size is not None:
file_object.set_large_file_size(st_size)
@@ -2762,9 +2409,12 @@ class FakeFilesystem:
return file_object
- def create_symlink(self, file_path: AnyPath,
- link_target: AnyPath,
- create_missing_dirs: bool = True) -> FakeFile:
+ def create_symlink(
+ self,
+ file_path: AnyPath,
+ link_target: AnyPath,
+ create_missing_dirs: bool = True,
+ ) -> FakeFile:
"""Create the specified symlink, pointed at the specified link target.
Args:
@@ -2794,8 +2444,9 @@ class FakeFilesystem:
if self.is_windows_fs:
self.raise_os_error(errno.EINVAL, link_target_path)
if not self.exists(
- self._path_without_trailing_separators(link_path),
- check_link=True):
+ self._path_without_trailing_separators(link_path),
+ check_link=True,
+ ):
self.raise_os_error(errno.ENOENT, link_target_path)
if self.is_macos:
# to avoid EEXIST exception, remove the link
@@ -2809,14 +2460,19 @@ class FakeFilesystem:
if not self.islink(link_path):
link_path = self.resolve_path(link_path)
return self.create_file_internally(
- link_path, st_mode=S_IFLNK | PERM_DEF,
+ link_path,
+ st_mode=S_IFLNK | helpers.PERM_DEF,
contents=link_target_path,
- create_missing_dirs=create_missing_dirs)
+ create_missing_dirs=create_missing_dirs,
+ )
- def create_link(self, old_path: AnyPath,
- new_path: AnyPath,
- follow_symlinks: bool = True,
- create_missing_dirs: bool = True) -> FakeFile:
+ def create_link(
+ self,
+ old_path: AnyPath,
+ new_path: AnyPath,
+ follow_symlinks: bool = True,
+ create_missing_dirs: bool = True,
+ ) -> FakeFile:
"""Create a hard link at new_path, pointing at old_path.
Args:
@@ -2841,8 +2497,7 @@ class FakeFilesystem:
if self.exists(new_path_normalized, check_link=True):
self.raise_os_error(errno.EEXIST, new_path_str)
- new_parent_directory, new_basename = self.splitpath(
- new_path_normalized)
+ new_parent_directory, new_basename = self.splitpath(new_path_normalized)
if not new_parent_directory:
new_parent_directory = matching_string(new_path_str, self.cwd)
@@ -2861,15 +2516,14 @@ class FakeFilesystem:
# Retrieve the target file
try:
- old_file = self.resolve(old_path_str,
- follow_symlinks=follow_symlinks)
+ old_file = self.resolve(old_path_str, follow_symlinks=follow_symlinks)
except OSError:
self.raise_os_error(errno.ENOENT, old_path_str)
if old_file.st_mode & S_IFDIR:
self.raise_os_error(
- errno.EACCES if self.is_windows_fs
- else errno.EPERM, old_path_str
+ errno.EACCES if self.is_windows_fs else errno.EPERM,
+ old_path_str,
)
# abuse the name field to control the filename of the
@@ -2878,9 +2532,12 @@ class FakeFilesystem:
self.add_object(new_parent_directory, old_file)
return old_file
- def link(self, old_path: AnyPath,
- new_path: AnyPath,
- follow_symlinks: bool = True) -> FakeFile:
+ def link(
+ self,
+ old_path: AnyPath,
+ new_path: AnyPath,
+ follow_symlinks: bool = True,
+ ) -> FakeFile:
"""Create a hard link at new_path, pointing at old_path.
Args:
@@ -2897,8 +2554,9 @@ class FakeFilesystem:
OSError: if old_path is a directory.
OSError: if the parent directory doesn't exist.
"""
- return self.create_link(old_path, new_path, follow_symlinks,
- create_missing_dirs=False)
+ return self.create_link(
+ old_path, new_path, follow_symlinks, create_missing_dirs=False
+ )
def _is_circular_link(self, link_obj: FakeFile) -> bool:
try:
@@ -2947,7 +2605,7 @@ class FakeFilesystem:
assert link_obj.contents
return link_obj.contents
- def makedir(self, dir_path: AnyPath, mode: int = PERM_DEF) -> None:
+ def makedir(self, dir_path: AnyPath, mode: int = helpers.PERM_DEF) -> None:
"""Create a leaf Fake directory.
Args:
@@ -2964,14 +2622,14 @@ class FakeFilesystem:
ends_with_sep = self.ends_with_path_separator(dir_name)
dir_name = self._path_without_trailing_separators(dir_name)
if not dir_name:
- self.raise_os_error(errno.ENOENT, '')
+ self.raise_os_error(errno.ENOENT, "")
if self.is_windows_fs:
dir_name = self.absnormpath(dir_name)
parent_dir, _ = self.splitpath(dir_name)
if parent_dir:
base_dir = self.normpath(parent_dir)
- ellipsis = matching_string(parent_dir, self.path_separator + '..')
+ ellipsis = matching_string(parent_dir, self.path_separator + "..")
if parent_dir.endswith(ellipsis) and not self.is_windows_fs:
base_dir, dummy_dotdot, _ = parent_dir.partition(ellipsis)
if not self.exists(base_dir):
@@ -2979,7 +2637,7 @@ class FakeFilesystem:
dir_name = self.absnormpath(dir_name)
if self.exists(dir_name, check_link=True):
- if self.is_windows_fs and dir_name == self.path_separator:
+ if self.is_windows_fs and dir_name == self.root_dir_name:
error_nr = errno.EACCES
else:
error_nr = errno.EEXIST
@@ -2992,16 +2650,17 @@ class FakeFilesystem:
self.add_object(
to_string(head),
- FakeDirectory(to_string(tail), mode & ~self.umask,
- filesystem=self))
+ FakeDirectory(to_string(tail), mode & ~self.umask, filesystem=self),
+ )
def _path_without_trailing_separators(self, path: AnyStr) -> AnyStr:
while self.ends_with_path_separator(path):
path = path[:-1]
return path
- def makedirs(self, dir_name: AnyStr, mode: int = PERM_DEF,
- exist_ok: bool = False) -> None:
+ def makedirs(
+ self, dir_name: AnyStr, mode: int = helpers.PERM_DEF, exist_ok: bool = False
+ ) -> None:
"""Create a leaf Fake directory and create any non-existent
parent dirs.
@@ -3018,12 +2677,15 @@ class FakeFilesystem:
or as per :py:meth:`create_dir`.
"""
if not dir_name:
- self.raise_os_error(errno.ENOENT, '')
+ self.raise_os_error(errno.ENOENT, "")
ends_with_sep = self.ends_with_path_separator(dir_name)
dir_name = self.absnormpath(dir_name)
- if (ends_with_sep and self.is_macos and
- self.exists(dir_name, check_link=True) and
- not self.exists(dir_name)):
+ if (
+ ends_with_sep
+ and self.is_macos
+ and self.exists(dir_name, check_link=True)
+ and not self.exists(dir_name)
+ ):
# to avoid EEXIST exception, remove the link
self.remove_object(dir_name)
@@ -3032,29 +2694,33 @@ class FakeFilesystem:
# Raise a permission denied error if the first existing directory
# is not writeable.
- current_dir = self.root
+ current_dir = self.root_dir
for component in path_components:
- if (not hasattr(current_dir, "entries") or
- component not in current_dir.entries):
+ if (
+ not hasattr(current_dir, "entries")
+ or component not in current_dir.entries
+ ):
break
else:
- current_dir = cast(FakeDirectory,
- current_dir.entries[component])
+ current_dir = cast(FakeDirectory, current_dir.entries[component])
try:
self.create_dir(dir_name, mode & ~self.umask)
except OSError as e:
if e.errno == errno.EACCES:
# permission denied - propagate exception
raise
- if (not exist_ok or
- not isinstance(self.resolve(dir_name), FakeDirectory)):
+ if not exist_ok or not isinstance(self.resolve(dir_name), FakeDirectory):
if self.is_windows_fs and e.errno == errno.ENOTDIR:
e.errno = errno.ENOENT
self.raise_os_error(e.errno, e.filename)
- def _is_of_type(self, path: AnyPath, st_flag: int,
- follow_symlinks: bool = True,
- check_read_perm: bool = True) -> bool:
+ def _is_of_type(
+ self,
+ path: AnyPath,
+ st_flag: int,
+ follow_symlinks: bool = True,
+ check_read_perm: bool = True,
+ ) -> bool:
"""Helper function to implement isdir(), islink(), etc.
See the stat(2) man page for valid stat.S_I* flag values
@@ -3075,11 +2741,13 @@ class FakeFilesystem:
raise TypeError
file_path = make_string_path(path)
try:
- obj = self.resolve(file_path, follow_symlinks,
- check_read_perm=check_read_perm)
+ obj = self.resolve(
+ file_path, follow_symlinks, check_read_perm=check_read_perm
+ )
if obj:
self.raise_for_filepath_ending_with_separator(
- file_path, obj, macos_handling=not follow_symlinks)
+ file_path, obj, macos_handling=not follow_symlinks
+ )
return S_IFMT(obj.st_mode) == st_flag
except OSError:
return False
@@ -3111,8 +2779,7 @@ class FakeFilesystem:
Raises:
TypeError: if path is None.
"""
- return self._is_of_type(path, S_IFREG, follow_symlinks,
- check_read_perm=False)
+ return self._is_of_type(path, S_IFREG, follow_symlinks, check_read_perm=False)
def islink(self, path: AnyPath) -> bool:
"""Determine if path identifies a symbolic link.
@@ -3128,13 +2795,23 @@ class FakeFilesystem:
"""
return self._is_of_type(path, S_IFLNK, follow_symlinks=False)
- def confirmdir(self, target_directory: AnyStr) -> FakeDirectory:
+ if sys.version_info >= (3, 12):
+
+ def isjunction(self, path: AnyPath) -> bool:
+ """Returns False. Junctions are never faked."""
+ return False
+
+ def confirmdir(
+ self, target_directory: AnyStr, check_owner: bool = False
+ ) -> FakeDirectory:
"""Test that the target is actually a directory, raising OSError
if not.
Args:
target_directory: Path to the target directory within the fake
filesystem.
+ check_owner: If True, only checks read permission if the current
+ user id is different from the file object user id
Returns:
The FakeDirectory object corresponding to target_directory.
@@ -3142,7 +2819,10 @@ class FakeFilesystem:
Raises:
OSError: if the target is not a directory.
"""
- directory = cast(FakeDirectory, self.resolve(target_directory))
+ directory = cast(
+ FakeDirectory,
+ self.resolve(target_directory, check_owner=check_owner),
+ )
if not directory.st_mode & S_IFDIR:
self.raise_os_error(errno.ENOTDIR, target_directory, 267)
return directory
@@ -3175,7 +2855,7 @@ class FakeFilesystem:
error = errno.EISDIR
self.raise_os_error(error, norm_path)
- if path.endswith(matching_string(path, self.path_separator)):
+ if path.endswith(self.get_path_separator(path)):
if self.is_windows_fs:
error = errno.EACCES
elif self.is_macos:
@@ -3188,8 +2868,7 @@ class FakeFilesystem:
self.remove_object(norm_path)
- def rmdir(self, target_directory: AnyStr,
- allow_symlink: bool = False) -> None:
+ def rmdir(self, target_directory: AnyStr, allow_symlink: bool = False) -> None:
"""Remove a leaf Fake directory.
Args:
@@ -3203,19 +2882,19 @@ class FakeFilesystem:
OSError: if removal failed per FakeFilesystem.RemoveObject.
Cannot remove '.'.
"""
- if target_directory == matching_string(target_directory, '.'):
+ if target_directory == matching_string(target_directory, "."):
error_nr = errno.EACCES if self.is_windows_fs else errno.EINVAL
self.raise_os_error(error_nr, target_directory)
ends_with_sep = self.ends_with_path_separator(target_directory)
target_directory = self.absnormpath(target_directory)
- if self.confirmdir(target_directory):
+ if self.confirmdir(target_directory, check_owner=True):
if not self.is_windows_fs and self.islink(target_directory):
if allow_symlink:
return
if not ends_with_sep or not self.is_macos:
self.raise_os_error(errno.ENOTDIR, target_directory)
- dir_object = self.resolve(target_directory)
+ dir_object = self.resolve(target_directory, check_owner=True)
if dir_object.entries:
self.raise_os_error(errno.ENOTEMPTY, target_directory)
self.remove_object(target_directory)
@@ -3243,2501 +2922,42 @@ class FakeFilesystem:
return directory_contents # type: ignore[return-value]
def __str__(self) -> str:
- return str(self.root)
+ return str(self.root_dir)
def _add_standard_streams(self) -> None:
self._add_open_file(StandardStreamWrapper(sys.stdin))
self._add_open_file(StandardStreamWrapper(sys.stdout))
self._add_open_file(StandardStreamWrapper(sys.stderr))
-
-Deprecator.add(FakeFilesystem, FakeFilesystem.get_disk_usage, 'GetDiskUsage')
-Deprecator.add(FakeFilesystem, FakeFilesystem.set_disk_usage, 'SetDiskUsage')
-Deprecator.add(FakeFilesystem,
- FakeFilesystem.change_disk_usage, 'ChangeDiskUsage')
-Deprecator.add(FakeFilesystem, FakeFilesystem.add_mount_point, 'AddMountPoint')
-Deprecator.add(FakeFilesystem, FakeFilesystem.stat, 'GetStat')
-Deprecator.add(FakeFilesystem, FakeFilesystem.chmod, 'ChangeMode')
-Deprecator.add(FakeFilesystem, FakeFilesystem.utime, 'UpdateTime')
-Deprecator.add(FakeFilesystem, FakeFilesystem._add_open_file, 'AddOpenFile')
-Deprecator.add(FakeFilesystem,
- FakeFilesystem._close_open_file, 'CloseOpenFile')
-Deprecator.add(FakeFilesystem, FakeFilesystem.has_open_file, 'HasOpenFile')
-Deprecator.add(FakeFilesystem, FakeFilesystem.get_open_file, 'GetOpenFile')
-Deprecator.add(FakeFilesystem,
- FakeFilesystem.normcase, 'NormalizePathSeparator')
-Deprecator.add(FakeFilesystem, FakeFilesystem.normpath, 'CollapsePath')
-Deprecator.add(FakeFilesystem, FakeFilesystem._original_path, 'NormalizeCase')
-Deprecator.add(FakeFilesystem, FakeFilesystem.absnormpath, 'NormalizePath')
-Deprecator.add(FakeFilesystem, FakeFilesystem.splitpath, 'SplitPath')
-Deprecator.add(FakeFilesystem, FakeFilesystem.splitdrive, 'SplitDrive')
-Deprecator.add(FakeFilesystem, FakeFilesystem.joinpaths, 'JoinPaths')
-Deprecator.add(FakeFilesystem,
- FakeFilesystem._path_components, 'GetPathComponents')
-Deprecator.add(FakeFilesystem, FakeFilesystem._starts_with_drive_letter,
- 'StartsWithDriveLetter')
-Deprecator.add(FakeFilesystem, FakeFilesystem.exists, 'Exists')
-Deprecator.add(FakeFilesystem, FakeFilesystem.resolve_path, 'ResolvePath')
-Deprecator.add(FakeFilesystem, FakeFilesystem.get_object_from_normpath,
- 'GetObjectFromNormalizedPath')
-Deprecator.add(FakeFilesystem, FakeFilesystem.get_object, 'GetObject')
-Deprecator.add(FakeFilesystem, FakeFilesystem.resolve, 'ResolveObject')
-Deprecator.add(FakeFilesystem, FakeFilesystem.lresolve, 'LResolveObject')
-Deprecator.add(FakeFilesystem, FakeFilesystem.add_object, 'AddObject')
-Deprecator.add(FakeFilesystem, FakeFilesystem.remove_object, 'RemoveObject')
-Deprecator.add(FakeFilesystem, FakeFilesystem.rename, 'RenameObject')
-Deprecator.add(FakeFilesystem, FakeFilesystem.create_dir, 'CreateDirectory')
-Deprecator.add(FakeFilesystem, FakeFilesystem.create_file, 'CreateFile')
-Deprecator.add(FakeFilesystem, FakeFilesystem.create_symlink, 'CreateLink')
-Deprecator.add(FakeFilesystem, FakeFilesystem.link, 'CreateHardLink')
-Deprecator.add(FakeFilesystem, FakeFilesystem.readlink, 'ReadLink')
-Deprecator.add(FakeFilesystem, FakeFilesystem.makedir, 'MakeDirectory')
-Deprecator.add(FakeFilesystem, FakeFilesystem.makedirs, 'MakeDirectories')
-Deprecator.add(FakeFilesystem, FakeFilesystem.isdir, 'IsDir')
-Deprecator.add(FakeFilesystem, FakeFilesystem.isfile, 'IsFile')
-Deprecator.add(FakeFilesystem, FakeFilesystem.islink, 'IsLink')
-Deprecator.add(FakeFilesystem, FakeFilesystem.confirmdir, 'ConfirmDir')
-Deprecator.add(FakeFilesystem, FakeFilesystem.remove, 'RemoveFile')
-Deprecator.add(FakeFilesystem, FakeFilesystem.rmdir, 'RemoveDirectory')
-Deprecator.add(FakeFilesystem, FakeFilesystem.listdir, 'ListDir')
-
-
-class FakePathModule:
- """Faked os.path module replacement.
-
- FakePathModule should *only* be instantiated by FakeOsModule. See the
- FakeOsModule docstring for details.
- """
- _OS_PATH_COPY: Any = _copy_module(os.path)
-
- devnull: ClassVar[str] = ''
- sep: ClassVar[str] = ''
- altsep: ClassVar[Optional[str]] = None
- linesep: ClassVar[str] = ''
- pathsep: ClassVar[str] = ''
-
- @staticmethod
- def dir() -> List[str]:
- """Return the list of patched function names. Used for patching
- functions imported from the module.
- """
- return [
- 'abspath', 'dirname', 'exists', 'expanduser', 'getatime',
- 'getctime', 'getmtime', 'getsize', 'isabs', 'isdir', 'isfile',
- 'islink', 'ismount', 'join', 'lexists', 'normcase', 'normpath',
- 'realpath', 'relpath', 'split', 'splitdrive', 'samefile'
- ]
-
- def __init__(self, filesystem: FakeFilesystem, os_module: 'FakeOsModule'):
- """Init.
-
- Args:
- filesystem: FakeFilesystem used to provide file system information
- """
- self.filesystem = filesystem
- self._os_path = self._OS_PATH_COPY
- self._os_path.os = self.os = os_module # type: ignore[attr-defined]
- self.reset(filesystem)
-
- @classmethod
- def reset(cls, filesystem: FakeFilesystem) -> None:
- cls.sep = filesystem.path_separator
- cls.altsep = filesystem.alternative_path_separator
- cls.linesep = filesystem.line_separator()
- cls.devnull = 'nul' if filesystem.is_windows_fs else '/dev/null'
- cls.pathsep = ';' if filesystem.is_windows_fs else ':'
-
- def exists(self, path: AnyStr) -> bool:
- """Determine whether the file object exists within the fake filesystem.
-
- Args:
- path: The path to the file object.
-
- Returns:
- (bool) `True` if the file exists.
- """
- return self.filesystem.exists(path)
-
- def lexists(self, path: AnyStr) -> bool:
- """Test whether a path exists. Returns True for broken symbolic links.
-
- Args:
- path: path to the symlink object.
-
- Returns:
- bool (if file exists).
- """
- return self.filesystem.exists(path, check_link=True)
-
- def getsize(self, path: AnyStr):
- """Return the file object size in bytes.
-
- Args:
- path: path to the file object.
-
- Returns:
- file size in bytes.
- """
- file_obj = self.filesystem.resolve(path)
- if (self.filesystem.ends_with_path_separator(path) and
- S_IFMT(file_obj.st_mode) != S_IFDIR):
- error_nr = (errno.EINVAL if self.filesystem.is_windows_fs
- else errno.ENOTDIR)
- self.filesystem.raise_os_error(error_nr, path)
- return file_obj.st_size
-
- def isabs(self, path: AnyStr) -> bool:
- """Return True if path is an absolute pathname."""
- if self.filesystem.is_windows_fs:
- path = self.splitdrive(path)[1]
- path = make_string_path(path)
- return self.filesystem._starts_with_sep(path)
-
- def isdir(self, path: AnyStr) -> bool:
- """Determine if path identifies a directory."""
- return self.filesystem.isdir(path)
-
- def isfile(self, path: AnyStr) -> bool:
- """Determine if path identifies a regular file."""
- return self.filesystem.isfile(path)
-
- def islink(self, path: AnyStr) -> bool:
- """Determine if path identifies a symbolic link.
-
- Args:
- path: Path to filesystem object.
-
- Returns:
- `True` if path points to a symbolic link.
-
- Raises:
- TypeError: if path is None.
- """
- return self.filesystem.islink(path)
-
- def getmtime(self, path: AnyStr) -> float:
- """Returns the modification time of the fake file.
-
- Args:
- path: the path to fake file.
-
- Returns:
- (int, float) the modification time of the fake file
- in number of seconds since the epoch.
-
- Raises:
- OSError: if the file does not exist.
- """
- try:
- file_obj = self.filesystem.resolve(path)
- return file_obj.st_mtime
- except OSError:
- self.filesystem.raise_os_error(errno.ENOENT, winerror=3)
-
- def getatime(self, path: AnyStr) -> float:
- """Returns the last access time of the fake file.
-
- Note: Access time is not set automatically in fake filesystem
- on access.
-
- Args:
- path: the path to fake file.
-
- Returns:
- (int, float) the access time of the fake file in number of seconds
- since the epoch.
-
- Raises:
- OSError: if the file does not exist.
- """
- try:
- file_obj = self.filesystem.resolve(path)
- except OSError:
- self.filesystem.raise_os_error(errno.ENOENT)
- return file_obj.st_atime
-
- def getctime(self, path: AnyStr) -> float:
- """Returns the creation time of the fake file.
-
- Args:
- path: the path to fake file.
-
- Returns:
- (int, float) the creation time of the fake file in number of
- seconds since the epoch.
-
- Raises:
- OSError: if the file does not exist.
- """
- try:
- file_obj = self.filesystem.resolve(path)
- except OSError:
- self.filesystem.raise_os_error(errno.ENOENT)
- return file_obj.st_ctime
-
- def abspath(self, path: AnyStr) -> AnyStr:
- """Return the absolute version of a path."""
-
- def getcwd():
- """Return the current working directory."""
- # pylint: disable=undefined-variable
- if isinstance(path, bytes):
- return self.os.getcwdb()
- else:
- return self.os.getcwd()
-
- path = make_string_path(path)
- if not self.isabs(path):
- path = self.join(getcwd(), path)
- elif (self.filesystem.is_windows_fs and
- self.filesystem._starts_with_sep(path)):
- cwd = getcwd()
- if self.filesystem._starts_with_drive_letter(cwd):
- path = self.join(cwd[:2], path)
- return self.normpath(path)
-
- def join(self, *p: AnyStr) -> AnyStr:
- """Return the completed path with a separator of the parts."""
- return self.filesystem.joinpaths(*p)
-
- def split(self, path: AnyStr) -> Tuple[AnyStr, AnyStr]:
- """Split the path into the directory and the filename of the path.
- """
- return self.filesystem.splitpath(path)
-
- def splitdrive(self, path: AnyStr) -> Tuple[AnyStr, AnyStr]:
- """Split the path into the drive part and the rest of the path, if
- supported."""
- return self.filesystem.splitdrive(path)
-
- def normpath(self, path: AnyStr) -> AnyStr:
- """Normalize path, eliminating double slashes, etc."""
- return self.filesystem.normpath(path)
-
- def normcase(self, path: AnyStr) -> AnyStr:
- """Convert to lower case under windows, replaces additional path
- separator."""
- path = self.filesystem.normcase(path)
- if self.filesystem.is_windows_fs:
- path = path.lower()
- return path
-
- def relpath(self, path: AnyStr, start: Optional[AnyStr] = None) -> AnyStr:
- """We mostly rely on the native implementation and adapt the
- path separator."""
- if not path:
- raise ValueError("no path specified")
- path = make_string_path(path)
- if start is not None:
- start = make_string_path(start)
- else:
- start = matching_string(path, self.filesystem.cwd)
- system_sep = matching_string(path, self._os_path.sep)
- if self.filesystem.alternative_path_separator is not None:
- altsep = matching_string(
- path, self.filesystem.alternative_path_separator)
- path = path.replace(altsep, system_sep)
- start = start.replace(altsep, system_sep)
- sep = matching_string(path, self.filesystem.path_separator)
- path = path.replace(sep, system_sep)
- start = start.replace(sep, system_sep)
- path = self._os_path.relpath(path, start)
- return path.replace(system_sep, sep)
-
- def realpath(self, filename: AnyStr, strict: bool = None) -> AnyStr:
- """Return the canonical path of the specified filename, eliminating any
- symbolic links encountered in the path.
- """
- if strict is not None and sys.version_info < (3, 10):
- raise TypeError("realpath() got an unexpected "
- "keyword argument 'strict'")
- if strict:
- # raises in strict mode if the file does not exist
- self.filesystem.resolve(filename)
- if self.filesystem.is_windows_fs:
- return self.abspath(filename)
- filename = make_string_path(filename)
- path, ok = self._join_real_path(filename[:0], filename, {})
- path = self.abspath(path)
- return path
-
- def samefile(self, path1: AnyStr, path2: AnyStr) -> bool:
- """Return whether path1 and path2 point to the same file.
-
- Args:
- path1: first file path or path object (Python >=3.6)
- path2: second file path or path object (Python >=3.6)
-
- Raises:
- OSError: if one of the paths does not point to an existing
- file system object.
- """
- stat1 = self.filesystem.stat(path1)
- stat2 = self.filesystem.stat(path2)
- return (stat1.st_ino == stat2.st_ino and
- stat1.st_dev == stat2.st_dev)
-
- @overload
- def _join_real_path(
- self, path: str,
- rest: str,
- seen: Dict[str, Optional[str]]) -> Tuple[str, bool]: ...
-
- @overload
- def _join_real_path(
- self, path: bytes,
- rest: bytes,
- seen: Dict[bytes, Optional[bytes]]) -> Tuple[bytes, bool]: ...
-
- def _join_real_path(
- self, path: AnyStr,
- rest: AnyStr,
- seen: Dict[AnyStr, Optional[AnyStr]]) -> Tuple[AnyStr, bool]:
- """Join two paths, normalizing and eliminating any symbolic links
- encountered in the second path.
- Taken from Python source and adapted.
- """
- curdir = matching_string(path, '.')
- pardir = matching_string(path, '..')
-
- sep = self.filesystem.get_path_separator(path)
- if self.isabs(rest):
- rest = rest[1:]
- path = sep
-
- while rest:
- name, _, rest = rest.partition(sep)
- if not name or name == curdir:
- # current dir
- continue
- if name == pardir:
- # parent dir
- if path:
- path, name = self.filesystem.splitpath(path)
- if name == pardir:
- path = self.filesystem.joinpaths(path, pardir, pardir)
- else:
- path = pardir
- continue
- newpath = self.filesystem.joinpaths(path, name)
- if not self.filesystem.islink(newpath):
- path = newpath
- continue
- # Resolve the symbolic link
- if newpath in seen:
- # Already seen this path
- seen_path = seen[newpath]
- if seen_path is not None:
- # use cached value
- path = seen_path
- continue
- # The symlink is not resolved, so we must have a symlink loop.
- # Return already resolved part + rest of the path unchanged.
- return self.filesystem.joinpaths(newpath, rest), False
- seen[newpath] = None # not resolved symlink
- path, ok = self._join_real_path(
- path, matching_string(path, self.filesystem.readlink(
- newpath)), seen)
- if not ok:
- return self.filesystem.joinpaths(path, rest), False
- seen[newpath] = path # resolved symlink
- return path, True
-
- def dirname(self, path: AnyStr) -> AnyStr:
- """Returns the first part of the result of `split()`."""
- return self.split(path)[0]
-
- def expanduser(self, path: AnyStr) -> AnyStr:
- """Return the argument with an initial component of ~ or ~user
- replaced by that user's home directory.
- """
- path = self._os_path.expanduser(path)
- return path.replace(
- matching_string(path, self._os_path.sep),
- matching_string(path, self.sep))
-
- def ismount(self, path: AnyStr) -> bool:
- """Return true if the given path is a mount point.
-
- Args:
- path: Path to filesystem object to be checked
-
- Returns:
- `True` if path is a mount point added to the fake file system.
- Under Windows also returns True for drive and UNC roots
- (independent of their existence).
- """
- if not path:
- return False
- path_str = to_string(make_string_path(path))
- normed_path = self.filesystem.absnormpath(path_str)
- sep = self.filesystem.path_separator
- if self.filesystem.is_windows_fs:
- path_seps: Union[Tuple[str, Optional[str]], Tuple[str]]
- if self.filesystem.alternative_path_separator is not None:
- path_seps = (
- sep, self.filesystem.alternative_path_separator
- )
- else:
- path_seps = (sep,)
- drive, rest = self.filesystem.splitdrive(normed_path)
- if drive and drive[:1] in path_seps:
- return (not rest) or (rest in path_seps)
- if rest in path_seps:
- return True
- for mount_point in self.filesystem.mount_points:
- if (to_string(normed_path).rstrip(sep) ==
- to_string(mount_point).rstrip(sep)):
- return True
- return False
-
- def __getattr__(self, name: str) -> Any:
- """Forwards any non-faked calls to the real os.path."""
- return getattr(self._os_path, name)
-
-
-class FakeOsModule:
- """Uses FakeFilesystem to provide a fake os module replacement.
-
- Do not create os.path separately from os, as there is a necessary circular
- dependency between os and os.path to replicate the behavior of the standard
- Python modules. What you want to do is to just let FakeOsModule take care
- of `os.path` setup itself.
-
- # You always want to do this.
- filesystem = fake_filesystem.FakeFilesystem()
- my_os_module = fake_filesystem.FakeOsModule(filesystem)
- """
-
- @staticmethod
- def dir() -> List[str]:
- """Return the list of patched function names. Used for patching
- functions imported from the module.
- """
- _dir = [
- 'access', 'chdir', 'chmod', 'chown', 'close', 'fstat', 'fsync',
- 'getcwd', 'lchmod', 'link', 'listdir', 'lstat', 'makedirs',
- 'mkdir', 'mknod', 'open', 'read', 'readlink', 'remove',
- 'removedirs', 'rename', 'rmdir', 'stat', 'symlink', 'umask',
- 'unlink', 'utime', 'walk', 'write', 'getcwdb', 'replace'
- ]
- if sys.platform.startswith('linux'):
- _dir += [
- 'fdatasync', 'getxattr', 'listxattr',
- 'removexattr', 'setxattr'
- ]
- if use_scandir:
- _dir += ['scandir']
- return _dir
-
- def __init__(self, filesystem: FakeFilesystem):
- """Also exposes self.path (to fake os.path).
-
- Args:
- filesystem: FakeFilesystem used to provide file system information
- """
- self.filesystem = filesystem
- self._os_module: Any = os
- self.path = FakePathModule(self.filesystem, self)
-
- @property
- def devnull(self) -> str:
- return self.path.devnull
-
- @property
- def sep(self) -> str:
- return self.path.sep
-
- @property
- def altsep(self) -> Optional[str]:
- return self.path.altsep
-
- @property
- def linesep(self) -> str:
- return self.path.linesep
-
- @property
- def pathsep(self) -> str:
- return self.path.pathsep
-
- def fdopen(self, fd: int, *args: Any, **kwargs: Any) -> AnyFileWrapper:
- """Redirector to open() builtin function.
-
- Args:
- fd: The file descriptor of the file to open.
- *args: Pass through args.
- **kwargs: Pass through kwargs.
-
- Returns:
- File object corresponding to file_des.
-
- Raises:
- TypeError: if file descriptor is not an integer.
- """
- if not is_int_type(fd):
- raise TypeError('an integer is required')
- return FakeFileOpen(self.filesystem)(fd, *args, **kwargs)
-
- def _umask(self) -> int:
- """Return the current umask."""
- if self.filesystem.is_windows_fs:
- # windows always returns 0 - it has no real notion of umask
- return 0
- if sys.platform == 'win32':
- # if we are testing Unix under Windows we assume a default mask
- return 0o002
- else:
- # under Unix, we return the real umask;
- # as there is no pure getter for umask, so we have to first
- # set a mode to get the previous one and then re-set that
- mask = os.umask(0)
- os.umask(mask)
- return mask
-
- def open(self, path: AnyStr, flags: int, mode: Optional[int] = None, *,
- dir_fd: Optional[int] = None) -> int:
- """Return the file descriptor for a FakeFile.
-
- Args:
- path: the path to the file
- flags: low-level bits to indicate io operation
- mode: bits to define default permissions
- Note: only basic modes are supported, OS-specific modes are
- ignored
- dir_fd: If not `None`, the file descriptor of a directory,
- with `file_path` being relative to this directory.
-
- Returns:
- A file descriptor.
-
- Raises:
- OSError: if the path cannot be found
- ValueError: if invalid mode is given
- NotImplementedError: if `os.O_EXCL` is used without `os.O_CREAT`
- """
- path = self._path_with_dir_fd(path, self.open, dir_fd)
- if mode is None:
- if self.filesystem.is_windows_fs:
- mode = 0o666
- else:
- mode = 0o777 & ~self._umask()
-
- has_tmpfile_flag = (hasattr(os, 'O_TMPFILE') and
- flags & getattr(os, 'O_TMPFILE'))
- open_modes = _OpenModes(
- must_exist=not flags & os.O_CREAT and not has_tmpfile_flag,
- can_read=not flags & os.O_WRONLY,
- can_write=flags & (os.O_RDWR | os.O_WRONLY) != 0,
- truncate=flags & os.O_TRUNC != 0,
- append=flags & os.O_APPEND != 0,
- must_not_exist=flags & os.O_EXCL != 0
- )
- if open_modes.must_not_exist and open_modes.must_exist:
- raise NotImplementedError(
- 'O_EXCL without O_CREAT mode is not supported')
- if has_tmpfile_flag:
- # this is a workaround for tempfiles that do not have a filename
- # as we do not support this directly, we just add a unique filename
- # and set the file to delete on close
- path = self.filesystem.joinpaths(
- path, matching_string(path, str(uuid.uuid4())))
-
- if (not self.filesystem.is_windows_fs and
- self.filesystem.exists(path)):
- # handle opening directory - only allowed under Posix
- # with read-only mode
- obj = self.filesystem.resolve(path)
- if isinstance(obj, FakeDirectory):
- if ((not open_modes.must_exist and
- not self.filesystem.is_macos)
- or open_modes.can_write):
- self.filesystem.raise_os_error(errno.EISDIR, path)
- dir_wrapper = FakeDirWrapper(obj, path, self.filesystem)
- file_des = self.filesystem._add_open_file(dir_wrapper)
- dir_wrapper.filedes = file_des
- return file_des
-
- # low level open is always binary
- str_flags = 'b'
- delete_on_close = has_tmpfile_flag
- if hasattr(os, 'O_TEMPORARY'):
- delete_on_close = flags & os.O_TEMPORARY == os.O_TEMPORARY
- fake_file = FakeFileOpen(
- self.filesystem, delete_on_close=delete_on_close, raw_io=True)(
- path, str_flags, open_modes=open_modes)
- assert not isinstance(fake_file, StandardStreamWrapper)
- if fake_file.file_object != self.filesystem.dev_null:
- self.chmod(path, mode)
- return fake_file.fileno()
-
- def close(self, fd: int) -> None:
- """Close a file descriptor.
-
- Args:
- fd: An integer file descriptor for the file object requested.
-
- Raises:
- OSError: bad file descriptor.
- TypeError: if file descriptor is not an integer.
- """
- file_handle = self.filesystem.get_open_file(fd)
- file_handle.close()
-
- def read(self, fd: int, n: int) -> bytes:
- """Read number of bytes from a file descriptor, returns bytes read.
-
- Args:
- fd: An integer file descriptor for the file object requested.
- n: Number of bytes to read from file.
-
- Returns:
- Bytes read from file.
-
- Raises:
- OSError: bad file descriptor.
- TypeError: if file descriptor is not an integer.
- """
- file_handle = self.filesystem.get_open_file(fd)
- if isinstance(file_handle, FakeFileWrapper):
- file_handle.raw_io = True
- if isinstance(file_handle, FakeDirWrapper):
- self.filesystem.raise_os_error(errno.EBADF, file_handle.file_path)
- return file_handle.read(n)
-
- def write(self, fd: int, contents: bytes) -> int:
- """Write string to file descriptor, returns number of bytes written.
-
- Args:
- fd: An integer file descriptor for the file object requested.
- contents: String of bytes to write to file.
-
- Returns:
- Number of bytes written.
-
- Raises:
- OSError: bad file descriptor.
- TypeError: if file descriptor is not an integer.
- """
- file_handle = cast(FakeFileWrapper, self.filesystem.get_open_file(fd))
- if isinstance(file_handle, FakeDirWrapper):
- self.filesystem.raise_os_error(errno.EBADF, file_handle.file_path)
-
- if isinstance(file_handle, FakePipeWrapper):
- return file_handle.write(contents)
-
- file_handle.raw_io = True
- file_handle._sync_io()
- file_handle.update_flush_pos()
- file_handle.write(contents)
- file_handle.flush()
- return len(contents)
-
- def pipe(self) -> Tuple[int, int]:
- read_fd, write_fd = os.pipe()
- read_wrapper = FakePipeWrapper(self.filesystem, read_fd, False)
- file_des = self.filesystem._add_open_file(read_wrapper)
- read_wrapper.filedes = file_des
- write_wrapper = FakePipeWrapper(self.filesystem, write_fd, True)
- file_des = self.filesystem._add_open_file(write_wrapper)
- write_wrapper.filedes = file_des
- return read_wrapper.filedes, write_wrapper.filedes
-
- @staticmethod
- def stat_float_times(newvalue: Optional[bool] = None) -> bool:
- """Determine whether a file's time stamps are reported as floats
- or ints.
-
- Calling without arguments returns the current value. The value is
- shared by all instances of FakeOsModule.
-
- Args:
- newvalue: If `True`, mtime, ctime, atime are reported as floats.
- Otherwise, they are returned as ints (rounding down).
- """
- return FakeStatResult.stat_float_times(newvalue)
-
- def fstat(self, fd: int) -> FakeStatResult:
- """Return the os.stat-like tuple for the FakeFile object of file_des.
-
- Args:
- fd: The file descriptor of filesystem object to retrieve.
-
- Returns:
- The FakeStatResult object corresponding to entry_path.
-
- Raises:
- OSError: if the filesystem object doesn't exist.
- """
- # stat should return the tuple representing return value of os.stat
- file_object = self.filesystem.get_open_file(fd).get_object()
- assert isinstance(file_object, FakeFile)
- return file_object.stat_result.copy()
-
- def umask(self, mask: int) -> int:
- """Change the current umask.
-
- Args:
- mask: (int) The new umask value.
-
- Returns:
- The old umask.
-
- Raises:
- TypeError: if new_mask is of an invalid type.
- """
- if not is_int_type(mask):
- raise TypeError('an integer is required')
- old_umask = self.filesystem.umask
- self.filesystem.umask = mask
- return old_umask
-
- def chdir(self, path: AnyStr) -> None:
- """Change current working directory to target directory.
-
- Args:
- path: The path to new current working directory.
-
- Raises:
- OSError: if user lacks permission to enter the argument directory
- or if the target is not a directory.
- """
- try:
- path = self.filesystem.resolve_path(
- path, allow_fd=True)
- except OSError as exc:
- if self.filesystem.is_macos and exc.errno == errno.EBADF:
- raise OSError(errno.ENOTDIR, "Not a directory: " + str(path))
- raise
- self.filesystem.confirmdir(path)
- directory = self.filesystem.resolve(path)
- # A full implementation would check permissions all the way
- # up the tree.
- if not is_root() and not directory.st_mode | PERM_EXE:
- self.filesystem.raise_os_error(errno.EACCES, directory.name)
- self.filesystem.cwd = path # type: ignore[assignment]
-
- def getcwd(self) -> str:
- """Return current working directory."""
- return to_string(self.filesystem.cwd)
-
- def getcwdb(self) -> bytes:
- """Return current working directory as bytes."""
- return to_bytes(self.filesystem.cwd)
-
- def listdir(self, path: AnyStr) -> List[AnyStr]:
- """Return a list of file names in target_directory.
-
- Args:
- path: Path to the target directory within the fake
- filesystem.
-
- Returns:
- A list of file names within the target directory in arbitrary
- order.
-
- Raises:
- OSError: if the target is not a directory.
- """
- return self.filesystem.listdir(path)
-
- XATTR_CREATE = 1
- XATTR_REPLACE = 2
-
- def getxattr(self, path: AnyStr, attribute: AnyString, *,
- follow_symlinks: bool = True) -> Optional[bytes]:
- """Return the value of the given extended filesystem attribute for
- `path`.
-
- Args:
- path: File path, file descriptor or path-like object (for
- Python >= 3.6).
- attribute: (str or bytes) The attribute name.
- follow_symlinks: (bool) If True (the default), symlinks in the
- path are traversed.
-
- Returns:
- The contents of the extended attribute as bytes or None if
- the attribute does not exist.
-
- Raises:
- OSError: if the path does not exist.
- """
- if not self.filesystem.is_linux:
- raise AttributeError(
- "module 'os' has no attribute 'getxattr'")
-
- if isinstance(attribute, bytes):
- attribute = attribute.decode(sys.getfilesystemencoding())
- file_obj = self.filesystem.resolve(path, follow_symlinks,
- allow_fd=True)
- return file_obj.xattr.get(attribute)
-
- def listxattr(self, path: Optional[AnyStr] = None, *,
- follow_symlinks: bool = True) -> List[str]:
- """Return a list of the extended filesystem attributes on `path`.
-
- Args:
- path: File path, file descriptor or path-like object (for
- Python >= 3.6). If None, the current directory is used.
- follow_symlinks: (bool) If True (the default), symlinks in the
- path are traversed.
-
- Returns:
- A list of all attribute names for the given path as str.
-
- Raises:
- OSError: if the path does not exist.
- """
- if not self.filesystem.is_linux:
- raise AttributeError(
- "module 'os' has no attribute 'listxattr'")
-
- path_str = self.filesystem.cwd if path is None else path
- file_obj = self.filesystem.resolve(
- cast(AnyStr, path_str), follow_symlinks, allow_fd=True)
- return list(file_obj.xattr.keys())
-
- def removexattr(self, path: AnyStr, attribute: AnyString, *,
- follow_symlinks: bool = True) -> None:
- """Removes the extended filesystem attribute attribute from `path`.
-
- Args:
- path: File path, file descriptor or path-like object (for
- Python >= 3.6).
- attribute: (str or bytes) The attribute name.
- follow_symlinks: (bool) If True (the default), symlinks in the
- path are traversed.
-
- Raises:
- OSError: if the path does not exist.
- """
- if not self.filesystem.is_linux:
- raise AttributeError(
- "module 'os' has no attribute 'removexattr'")
-
- if isinstance(attribute, bytes):
- attribute = attribute.decode(sys.getfilesystemencoding())
- file_obj = self.filesystem.resolve(path, follow_symlinks,
- allow_fd=True)
- if attribute in file_obj.xattr:
- del file_obj.xattr[attribute]
-
- def setxattr(self, path: AnyStr, attribute: AnyString, value: bytes,
- flags: int = 0, *, follow_symlinks: bool = True) -> None:
- """Sets the value of the given extended filesystem attribute for
- `path`.
-
- Args:
- path: File path, file descriptor or path-like object (for
- Python >= 3.6).
- attribute: The attribute name (str or bytes).
- value: (byte-like) The value to be set.
- follow_symlinks: (bool) If True (the default), symlinks in the
- path are traversed.
-
- Raises:
- OSError: if the path does not exist.
- TypeError: if `value` is not a byte-like object.
- """
- if not self.filesystem.is_linux:
- raise AttributeError(
- "module 'os' has no attribute 'setxattr'")
-
- if isinstance(attribute, bytes):
- attribute = attribute.decode(sys.getfilesystemencoding())
- if not is_byte_string(value):
- raise TypeError('a bytes-like object is required')
- file_obj = self.filesystem.resolve(path, follow_symlinks,
- allow_fd=True)
- exists = attribute in file_obj.xattr
- if exists and flags == self.XATTR_CREATE:
- self.filesystem.raise_os_error(errno.ENODATA, file_obj.path)
- if not exists and flags == self.XATTR_REPLACE:
- self.filesystem.raise_os_error(errno.EEXIST, file_obj.path)
- file_obj.xattr[attribute] = value
-
- def scandir(self, path: str = '.') -> ScanDirIter:
- """Return an iterator of DirEntry objects corresponding to the
- entries in the directory given by path.
-
- Args:
- path: Path to the target directory within the fake filesystem.
-
- Returns:
- An iterator to an unsorted list of os.DirEntry objects for
- each entry in path.
-
- Raises:
- OSError: if the target is not a directory.
- """
- return scandir(self.filesystem, path)
-
- def walk(self, top: AnyStr, topdown: bool = True,
- onerror: Optional[bool] = None,
- followlinks: bool = False):
- """Perform an os.walk operation over the fake filesystem.
-
- Args:
- top: The root directory from which to begin walk.
- topdown: Determines whether to return the tuples with the root as
- the first entry (`True`) or as the last, after all the child
- directory tuples (`False`).
- onerror: If not `None`, function which will be called to handle the
- `os.error` instance provided when `os.listdir()` fails.
- followlinks: If `True`, symbolic links are followed.
-
- Yields:
- (path, directories, nondirectories) for top and each of its
- subdirectories. See the documentation for the builtin os module
- for further details.
- """
- return walk(self.filesystem, top, topdown, onerror, followlinks)
-
- def readlink(self, path: AnyStr, dir_fd: Optional[int] = None) -> str:
- """Read the target of a symlink.
-
- Args:
- path: Symlink to read the target of.
- dir_fd: If not `None`, the file descriptor of a directory,
- with `path` being relative to this directory.
-
- Returns:
- the string representing the path to which the symbolic link points.
-
- Raises:
- TypeError: if `path` is None
- OSError: (with errno=ENOENT) if path is not a valid path, or
- (with errno=EINVAL) if path is valid, but is not a symlink
- """
- path = self._path_with_dir_fd(path, self.readlink, dir_fd)
- return self.filesystem.readlink(path)
-
- def stat(self, path: AnyStr, *, dir_fd: Optional[int] = None,
- follow_symlinks: bool = True) -> FakeStatResult:
- """Return the os.stat-like tuple for the FakeFile object of entry_path.
-
- Args:
- path: path to filesystem object to retrieve.
- dir_fd: (int) If not `None`, the file descriptor of a directory,
- with `entry_path` being relative to this directory.
- follow_symlinks: (bool) If `False` and `entry_path` points to a
- symlink, the link itself is changed instead of the linked
- object.
-
- Returns:
- The FakeStatResult object corresponding to entry_path.
-
- Raises:
- OSError: if the filesystem object doesn't exist.
- """
- path = self._path_with_dir_fd(path, self.stat, dir_fd)
- return self.filesystem.stat(path, follow_symlinks)
-
- def lstat(self, path: AnyStr, *,
- dir_fd: Optional[int] = None) -> FakeStatResult:
- """Return the os.stat-like tuple for entry_path, not following symlinks.
-
- Args:
- path: path to filesystem object to retrieve.
- dir_fd: If not `None`, the file descriptor of a directory, with
- `path` being relative to this directory.
-
- Returns:
- the FakeStatResult object corresponding to `path`.
-
- Raises:
- OSError: if the filesystem object doesn't exist.
- """
- # stat should return the tuple representing return value of os.stat
- path = self._path_with_dir_fd(path, self.lstat, dir_fd)
- return self.filesystem.stat(path, follow_symlinks=False)
-
- def remove(self, path: AnyStr, dir_fd: Optional[int] = None) -> None:
- """Remove the FakeFile object at the specified file path.
-
- Args:
- path: Path to file to be removed.
- dir_fd: If not `None`, the file descriptor of a directory,
- with `path` being relative to this directory.
-
- Raises:
- OSError: if path points to a directory.
- OSError: if path does not exist.
- OSError: if removal failed.
- """
- path = self._path_with_dir_fd(path, self.remove, dir_fd)
- self.filesystem.remove(path)
-
- def unlink(self, path: AnyStr, *, dir_fd: Optional[int] = None) -> None:
- """Remove the FakeFile object at the specified file path.
-
- Args:
- path: Path to file to be removed.
- dir_fd: If not `None`, the file descriptor of a directory,
- with `path` being relative to this directory.
-
- Raises:
- OSError: if path points to a directory.
- OSError: if path does not exist.
- OSError: if removal failed.
- """
- path = self._path_with_dir_fd(path, self.unlink, dir_fd)
- self.filesystem.remove(path)
-
- def rename(self, src: AnyStr, dst: AnyStr, *,
- src_dir_fd: Optional[int] = None,
- dst_dir_fd: Optional[int] = None) -> None:
- """Rename a FakeFile object at old_file_path to new_file_path,
- preserving all properties.
- Also replaces existing new_file_path object, if one existed
- (Unix only).
-
- Args:
- src: Path to filesystem object to rename.
- dst: Path to where the filesystem object will live
- after this call.
- src_dir_fd: If not `None`, the file descriptor of a directory,
- with `src` being relative to this directory.
- dst_dir_fd: If not `None`, the file descriptor of a directory,
- with `dst` being relative to this directory.
-
- Raises:
- OSError: if old_file_path does not exist.
- OSError: if new_file_path is an existing directory.
- OSError: if new_file_path is an existing file (Windows only)
- OSError: if new_file_path is an existing file and could not
- be removed (Unix)
- OSError: if `dirname(new_file)` does not exist
- OSError: if the file would be moved to another filesystem
- (e.g. mount point)
- """
- src = self._path_with_dir_fd(src, self.rename, src_dir_fd)
- dst = self._path_with_dir_fd(dst, self.rename, dst_dir_fd)
- self.filesystem.rename(src, dst)
-
- def replace(self, src: AnyStr, dst: AnyStr, *,
- src_dir_fd: Optional[int] = None,
- dst_dir_fd: Optional[int] = None) -> None:
- """Renames a FakeFile object at old_file_path to new_file_path,
- preserving all properties.
- Also replaces existing new_file_path object, if one existed.
-
- Arg
- src: Path to filesystem object to rename.
- dst: Path to where the filesystem object will live
- after this call.
- src_dir_fd: If not `None`, the file descriptor of a directory,
- with `src` being relative to this directory.
- dst_dir_fd: If not `None`, the file descriptor of a directory,
- with `dst` being relative to this directory.
-
- Raises:
- OSError: if old_file_path does not exist.
- OSError: if new_file_path is an existing directory.
- OSError: if new_file_path is an existing file and could
- not be removed
- OSError: if `dirname(new_file)` does not exist
- OSError: if the file would be moved to another filesystem
- (e.g. mount point)
- """
- src = self._path_with_dir_fd(src, self.rename, src_dir_fd)
- dst = self._path_with_dir_fd(dst, self.rename, dst_dir_fd)
- self.filesystem.rename(src, dst, force_replace=True)
-
- def rmdir(self, path: AnyStr, *, dir_fd: Optional[int] = None) -> None:
- """Remove a leaf Fake directory.
-
- Args:
- path: (str) Name of directory to remove.
- dir_fd: If not `None`, the file descriptor of a directory,
- with `path` being relative to this directory.
-
- Raises:
- OSError: if `path` does not exist or is not a directory,
- or as per FakeFilesystem.remove_object. Cannot remove '.'.
- """
- path = self._path_with_dir_fd(path, self.rmdir, dir_fd)
- self.filesystem.rmdir(path)
-
- def removedirs(self, name: AnyStr) -> None:
- """Remove a leaf fake directory and all empty intermediate ones.
-
- Args:
- name: the directory to be removed.
-
- Raises:
- OSError: if target_directory does not exist or is not a directory.
- OSError: if target_directory is not empty.
- """
- name = self.filesystem.absnormpath(name)
- directory = self.filesystem.confirmdir(name)
- if directory.entries:
- self.filesystem.raise_os_error(
- errno.ENOTEMPTY, self.path.basename(name))
- else:
- self.rmdir(name)
- head, tail = self.path.split(name)
- if not tail:
- head, tail = self.path.split(head)
- while head and tail:
- head_dir = self.filesystem.confirmdir(head)
- if head_dir.entries:
- break
- # only the top-level dir may not be a symlink
- self.filesystem.rmdir(head, allow_symlink=True)
- head, tail = self.path.split(head)
-
- def mkdir(self, path: AnyStr, mode: int = PERM_DEF, *,
- dir_fd: Optional[int] = None) -> None:
- """Create a leaf Fake directory.
-
- Args:
- path: (str) Name of directory to create.
- Relative paths are assumed to be relative to '/'.
- mode: (int) Mode to create directory with. This argument defaults
- to 0o777. The umask is applied to this mode.
- dir_fd: If not `None`, the file descriptor of a directory,
- with `path` being relative to this directory.
-
- Raises:
- OSError: if the directory name is invalid or parent directory is
- read only or as per FakeFilesystem.add_object.
- """
- path = self._path_with_dir_fd(path, self.mkdir, dir_fd)
- try:
- self.filesystem.makedir(path, mode)
- except OSError as e:
- if e.errno == errno.EACCES:
- self.filesystem.raise_os_error(e.errno, path)
- raise
-
- def makedirs(self, name: AnyStr, mode: int = PERM_DEF,
- exist_ok: bool = None) -> None:
- """Create a leaf Fake directory + create any non-existent parent dirs.
-
- Args:
- name: (str) Name of directory to create.
- mode: (int) Mode to create directory (and any necessary parent
- directories) with. This argument defaults to 0o777.
- The umask is applied to this mode.
- exist_ok: (boolean) If exist_ok is False (the default), an OSError
- is raised if the target directory already exists.
-
- Raises:
- OSError: if the directory already exists and exist_ok=False, or as
- per :py:meth:`FakeFilesystem.create_dir`.
- """
- if exist_ok is None:
- exist_ok = False
- self.filesystem.makedirs(name, mode, exist_ok)
-
- def _path_with_dir_fd(self, path: AnyStr, fct: Callable,
- dir_fd: Optional[int]) -> AnyStr:
- """Return the path considering dir_fd. Raise on invalid parameters."""
- try:
- path = make_string_path(path)
- except TypeError:
- # the error is handled later
- path = path
- if dir_fd is not None:
- # check if fd is supported for the built-in real function
- real_fct = getattr(os, fct.__name__)
- if real_fct not in self.supports_dir_fd:
- raise NotImplementedError(
- 'dir_fd unavailable on this platform')
- if isinstance(path, int):
- raise ValueError("%s: Can't specify dir_fd without "
- "matching path_str" % fct.__name__)
- if not self.path.isabs(path):
- open_file = self.filesystem.get_open_file(dir_fd)
- return self.path.join( # type: ignore[type-var, return-value]
- cast(FakeFile, open_file.get_object()).path, path)
- return path
-
- def truncate(self, path: AnyStr, length: int) -> None:
- """Truncate the file corresponding to path, so that it is
- length bytes in size. If length is larger than the current size,
- the file is filled up with zero bytes.
-
- Args:
- path: (str or int) Path to the file, or an integer file
- descriptor for the file object.
- length: (int) Length of the file after truncating it.
-
- Raises:
- OSError: if the file does not exist or the file descriptor is
- invalid.
- """
- file_object = self.filesystem.resolve(path, allow_fd=True)
- file_object.size = length
-
- def ftruncate(self, fd: int, length: int) -> None:
- """Truncate the file corresponding to fd, so that it is
- length bytes in size. If length is larger than the current size,
- the file is filled up with zero bytes.
-
- Args:
- fd: (int) File descriptor for the file object.
- length: (int) Maximum length of the file after truncating it.
-
- Raises:
- OSError: if the file descriptor is invalid
- """
- file_object = self.filesystem.get_open_file(fd).get_object()
- if isinstance(file_object, FakeFileWrapper):
- file_object.size = length
- else:
- raise OSError(errno.EBADF, 'Invalid file descriptor')
-
- def access(self, path: AnyStr, mode: int, *,
- dir_fd: Optional[int] = None,
- effective_ids: bool = False,
- follow_symlinks: bool = True) -> bool:
- """Check if a file exists and has the specified permissions.
-
- Args:
- path: (str) Path to the file.
- mode: (int) Permissions represented as a bitwise-OR combination of
- os.F_OK, os.R_OK, os.W_OK, and os.X_OK.
- dir_fd: If not `None`, the file descriptor of a directory, with
- `path` being relative to this directory.
- effective_ids: (bool) Unused. Only here to match the signature.
- follow_symlinks: (bool) If `False` and `path` points to a symlink,
- the link itself is queried instead of the linked object.
-
- Returns:
- bool, `True` if file is accessible, `False` otherwise.
- """
- if effective_ids and self.filesystem.is_windows_fs:
- raise NotImplementedError(
- 'access: effective_ids unavailable on this platform')
- path = self._path_with_dir_fd(path, self.access, dir_fd)
- try:
- stat_result = self.stat(path, follow_symlinks=follow_symlinks)
- except OSError as os_error:
- if os_error.errno == errno.ENOENT:
- return False
- raise
- if is_root():
- mode &= ~os.W_OK
- return (mode & ((stat_result.st_mode >> 6) & 7)) == mode
-
- def chmod(self, path: AnyStr, mode: int, *,
- dir_fd: Optional[int] = None,
- follow_symlinks: bool = True) -> None:
- """Change the permissions of a file as encoded in integer mode.
-
- Args:
- path: (str) Path to the file.
- mode: (int) Permissions.
- dir_fd: If not `None`, the file descriptor of a directory, with
- `path` being relative to this directory.
- follow_symlinks: (bool) If `False` and `path` points to a symlink,
- the link itself is queried instead of the linked object.
- """
- if (not follow_symlinks and
- (os.chmod not in os.supports_follow_symlinks or IS_PYPY)):
- raise NotImplementedError(
- "`follow_symlinks` for chmod() is not available "
- "on this system")
- path = self._path_with_dir_fd(path, self.chmod, dir_fd)
- self.filesystem.chmod(path, mode, follow_symlinks)
-
- def lchmod(self, path: AnyStr, mode: int) -> None:
- """Change the permissions of a file as encoded in integer mode.
- If the file is a link, the permissions of the link are changed.
-
- Args:
- path: (str) Path to the file.
- mode: (int) Permissions.
- """
- if self.filesystem.is_windows_fs:
- raise NameError("name 'lchmod' is not defined")
- self.filesystem.chmod(path, mode, follow_symlinks=False)
-
- def utime(self, path: AnyStr,
- times: Optional[Tuple[Union[int, float], Union[int, float]]] =
- None, ns: Optional[Tuple[int, int]] = None,
- dir_fd: Optional[int] = None,
- follow_symlinks: bool = True) -> None:
- """Change the access and modified times of a file.
-
- Args:
- path: (str) Path to the file.
- times: 2-tuple of int or float numbers, of the form (atime, mtime)
- which is used to set the access and modified times in seconds.
- If None, both times are set to the current time.
- ns: 2-tuple of int numbers, of the form (atime, mtime) which is
- used to set the access and modified times in nanoseconds.
- If None, both times are set to the current time.
- dir_fd: If not `None`, the file descriptor of a directory,
- with `path` being relative to this directory.
- follow_symlinks: (bool) If `False` and `path` points to a symlink,
- the link itself is queried instead of the linked object.
-
- Raises:
- TypeError: If anything other than the expected types is
- specified in the passed `times` or `ns` tuple,
- or if the tuple length is not equal to 2.
- ValueError: If both times and ns are specified.
- """
- path = self._path_with_dir_fd(path, self.utime, dir_fd)
- self.filesystem.utime(
- path, times=times, ns=ns, follow_symlinks=follow_symlinks)
-
- def chown(self, path: AnyStr, uid: int, gid: int, *,
- dir_fd: Optional[int] = None,
- follow_symlinks: bool = True) -> None:
- """Set ownership of a faked file.
-
- Args:
- path: (str) Path to the file or directory.
- uid: (int) Numeric uid to set the file or directory to.
- gid: (int) Numeric gid to set the file or directory to.
- dir_fd: (int) If not `None`, the file descriptor of a directory,
- with `path` being relative to this directory.
- follow_symlinks: (bool) If `False` and path points to a symlink,
- the link itself is changed instead of the linked object.
-
- Raises:
- OSError: if path does not exist.
-
- `None` is also allowed for `uid` and `gid`. This permits `os.rename`
- to use `os.chown` even when the source file `uid` and `gid` are
- `None` (unset).
- """
- path = self._path_with_dir_fd(path, self.chown, dir_fd)
- file_object = self.filesystem.resolve(
- path, follow_symlinks, allow_fd=True)
- if not ((is_int_type(uid) or uid is None) and
- (is_int_type(gid) or gid is None)):
- raise TypeError("An integer is required")
- if uid != -1:
- file_object.st_uid = uid
- if gid != -1:
- file_object.st_gid = gid
-
- def mknod(self, path: AnyStr, mode: Optional[int] = None,
- device: int = 0, *,
- dir_fd: Optional[int] = None) -> None:
- """Create a filesystem node named 'filename'.
-
- Does not support device special files or named pipes as the real os
- module does.
-
- Args:
- path: (str) Name of the file to create
- mode: (int) Permissions to use and type of file to be created.
- Default permissions are 0o666. Only the stat.S_IFREG file type
- is supported by the fake implementation. The umask is applied
- to this mode.
- device: not supported in fake implementation
- dir_fd: If not `None`, the file descriptor of a directory,
- with `path` being relative to this directory.
-
- Raises:
- OSError: if called with unsupported options or the file can not be
- created.
- """
- if self.filesystem.is_windows_fs:
- raise AttributeError("module 'os' has no attribute 'mknode'")
- if mode is None:
- # note that a default value of 0o600 without a device type is
- # documented - this is not how it seems to work
- mode = S_IFREG | 0o600
- if device or not mode & S_IFREG and not is_root():
- self.filesystem.raise_os_error(errno.EPERM)
-
- path = self._path_with_dir_fd(path, self.mknod, dir_fd)
- head, tail = self.path.split(path)
- if not tail:
- if self.filesystem.exists(head, check_link=True):
- self.filesystem.raise_os_error(errno.EEXIST, path)
- self.filesystem.raise_os_error(errno.ENOENT, path)
- if tail in (matching_string(tail, '.'), matching_string(tail, '..')):
- self.filesystem.raise_os_error(errno.ENOENT, path)
- if self.filesystem.exists(path, check_link=True):
- self.filesystem.raise_os_error(errno.EEXIST, path)
- self.filesystem.add_object(head, FakeFile(
- tail, mode & ~self.filesystem.umask,
- filesystem=self.filesystem))
-
- def symlink(self, src: AnyStr, dst: AnyStr, *,
- dir_fd: Optional[int] = None) -> None:
- """Creates the specified symlink, pointed at the specified link target.
-
- Args:
- src: The target of the symlink.
- dst: Path to the symlink to create.
- dir_fd: If not `None`, the file descriptor of a directory,
- with `src` being relative to this directory.
-
- Raises:
- OSError: if the file already exists.
- """
- src = self._path_with_dir_fd(src, self.symlink, dir_fd)
- self.filesystem.create_symlink(
- dst, src, create_missing_dirs=False)
-
- def link(self, src: AnyStr, dst: AnyStr, *,
- src_dir_fd: Optional[int] = None,
- dst_dir_fd: Optional[int] = None) -> None:
- """Create a hard link at new_path, pointing at old_path.
-
- Args:
- src: An existing path to the target file.
- dst: The destination path to create a new link at.
- src_dir_fd: If not `None`, the file descriptor of a directory,
- with `src` being relative to this directory.
- dst_dir_fd: If not `None`, the file descriptor of a directory,
- with `dst` being relative to this directory.
-
- Raises:
- OSError: if something already exists at new_path.
- OSError: if the parent directory doesn't exist.
- """
- src = self._path_with_dir_fd(src, self.link, src_dir_fd)
- dst = self._path_with_dir_fd(dst, self.link, dst_dir_fd)
- self.filesystem.link(src, dst)
-
- def fsync(self, fd: int) -> None:
- """Perform fsync for a fake file (in other words, do nothing).
-
- Args:
- fd: The file descriptor of the open file.
-
- Raises:
- OSError: file_des is an invalid file descriptor.
- TypeError: file_des is not an integer.
- """
- # Throw an error if file_des isn't valid
- if 0 <= fd < NR_STD_STREAMS:
- self.filesystem.raise_os_error(errno.EINVAL)
- file_object = cast(FakeFileWrapper, self.filesystem.get_open_file(fd))
- if self.filesystem.is_windows_fs:
- if (not hasattr(file_object, 'allow_update') or
- not file_object.allow_update):
- self.filesystem.raise_os_error(
- errno.EBADF, file_object.file_path)
-
- def fdatasync(self, fd: int) -> None:
- """Perform fdatasync for a fake file (in other words, do nothing).
-
- Args:
- fd: The file descriptor of the open file.
-
- Raises:
- OSError: `fd` is an invalid file descriptor.
- TypeError: `fd` is not an integer.
- """
- if self.filesystem.is_windows_fs or self.filesystem.is_macos:
- raise AttributeError("module 'os' has no attribute 'fdatasync'")
- # Throw an error if file_des isn't valid
- if 0 <= fd < NR_STD_STREAMS:
- self.filesystem.raise_os_error(errno.EINVAL)
- self.filesystem.get_open_file(fd)
-
- def sendfile(self, fd_out: int, fd_in: int,
- offset: int, count: int) -> int:
- """Copy count bytes from file descriptor fd_in to file descriptor
- fd_out starting at offset.
-
- Args:
- fd_out: The file descriptor of the destination file.
- fd_in: The file descriptor of the source file.
- offset: The offset in bytes where to start the copy in the
- source file. If `None` (Linux only), copying is started at
- the current position, and the position is updated.
- count: The number of bytes to copy. If 0, all remaining bytes
- are copied (MacOs only).
-
- Raises:
- OSError: If `fd_in` or `fd_out` is an invalid file descriptor.
- TypeError: If `fd_in` or `fd_out` is not an integer.
- TypeError: If `offset` is None under MacOs.
- """
- if self.filesystem.is_windows_fs:
- raise AttributeError("module 'os' has no attribute 'sendfile'")
- if 0 <= fd_in < NR_STD_STREAMS:
- self.filesystem.raise_os_error(errno.EINVAL)
- if 0 <= fd_out < NR_STD_STREAMS:
- self.filesystem.raise_os_error(errno.EINVAL)
- source = cast(FakeFileWrapper, self.filesystem.get_open_file(fd_in))
- dest = cast(FakeFileWrapper, self.filesystem.get_open_file(fd_out))
- if self.filesystem.is_macos:
- if dest.get_object().stat_result.st_mode & 0o777000 != S_IFSOCK:
- raise OSError('Socket operation on non-socket')
- if offset is None:
- if self.filesystem.is_macos:
- raise TypeError('None is not a valid offset')
- contents = source.read(count)
- else:
- position = source.tell()
- source.seek(offset)
- if count == 0 and self.filesystem.is_macos:
- contents = source.read()
- else:
- contents = source.read(count)
- source.seek(position)
- if contents:
- written = dest.write(contents)
- dest.flush()
- return written
- return 0
-
- def __getattr__(self, name: str) -> Any:
- """Forwards any unfaked calls to the standard os module."""
- return getattr(self._os_module, name)
-
-
-class FakeIoModule:
- """Uses FakeFilesystem to provide a fake io module replacement.
-
- Currently only used to wrap `io.open()` which is an alias to `open()`.
-
- You need a fake_filesystem to use this:
- filesystem = fake_filesystem.FakeFilesystem()
- my_io_module = fake_filesystem.FakeIoModule(filesystem)
- """
-
- @staticmethod
- def dir() -> List[str]:
- """Return the list of patched function names. Used for patching
- functions imported from the module.
- """
- _dir = ['open']
- if sys.version_info >= (3, 8):
- _dir.append('open_code')
- return _dir
-
- def __init__(self, filesystem: FakeFilesystem):
- """
- Args:
- filesystem: FakeFilesystem used to provide file system information.
- """
- self.filesystem = filesystem
- self.skip_names: List[str] = []
- self._io_module = io
-
- def open(self, file: Union[AnyStr, int],
- mode: str = 'r', buffering: int = -1,
- encoding: Optional[str] = None,
- errors: Optional[str] = None,
- newline: Optional[str] = None,
- closefd: bool = True,
- opener: Optional[Callable] = None) -> Union[AnyFileWrapper,
- IO[Any]]:
- """Redirect the call to FakeFileOpen.
- See FakeFileOpen.call() for description.
- """
- # workaround for built-in open called from skipped modules (see #552)
- # as open is not imported explicitly, we cannot patch it for
- # specific modules; instead we check if the caller is a skipped
- # module (should work in most cases)
- stack = traceback.extract_stack(limit=2)
- module_name = os.path.splitext(stack[0].filename)[0]
- module_name = module_name.replace(os.sep, '.')
- if any([module_name == sn or module_name.endswith('.' + sn)
- for sn in self.skip_names]):
- return io.open(file, mode, buffering, encoding, errors,
- newline, closefd, opener)
- fake_open = FakeFileOpen(self.filesystem)
- return fake_open(file, mode, buffering, encoding, errors,
- newline, closefd, opener)
-
- if sys.version_info >= (3, 8):
- def open_code(self, path):
- """Redirect the call to open. Note that the behavior of the real
- function may be overridden by an earlier call to the
- PyFile_SetOpenCodeHook(). This behavior is not reproduced here.
- """
- if not isinstance(path, str):
- raise TypeError(
- "open_code() argument 'path' must be str, not int")
- patch_mode = self.filesystem.patch_open_code
- if (patch_mode == PatchMode.AUTO and self.filesystem.exists(path)
- or patch_mode == PatchMode.ON):
- return self.open(path, mode='rb')
- # mostly this is used for compiled code -
- # don't patch these, as the files are probably in the real fs
- return self._io_module.open_code(path)
-
- def __getattr__(self, name):
- """Forwards any unfaked calls to the standard io module."""
- return getattr(self._io_module, name)
-
-
-if sys.platform != 'win32':
- import fcntl
-
- class FakeFcntlModule:
- """Replaces the fcntl module. Only valid under Linux/MacOS,
- currently just mocks the functionality away.
- """
-
- @staticmethod
- def dir() -> List[str]:
- """Return the list of patched function names. Used for patching
- functions imported from the module.
- """
- return ['fcntl', 'ioctl', 'flock', 'lockf']
-
- def __init__(self, filesystem: FakeFilesystem):
- """
- Args:
- filesystem: FakeFilesystem used to provide file system
- information (currently not used).
- """
- self.filesystem = filesystem
- self._fcntl_module = fcntl
-
- def fcntl(self, fd: int, cmd: int, arg: int = 0) -> Union[int, bytes]:
- return 0
-
- def ioctl(self, fd: int, request: int, arg: int = 0,
- mutate_flag: bool = True) -> Union[int, bytes]:
- return 0
-
- def flock(self, fd: int, operation: int) -> None:
- pass
-
- def lockf(self, fd: int, cmd: int, len: int = 0,
- start: int = 0, whence=0) -> Any:
- pass
-
- def __getattr__(self, name):
- """Forwards any unfaked calls to the standard fcntl module."""
- return getattr(self._fcntl_module, name)
-
-
-class FakeFileWrapper:
- """Wrapper for a stream object for use by a FakeFile object.
-
- If the wrapper has any data written to it, it will propagate to
- the FakeFile object on close() or flush().
- """
-
- def __init__(self, file_object: FakeFile,
- file_path: AnyStr,
- update: bool, read: bool, append: bool, delete_on_close: bool,
- filesystem: FakeFilesystem,
- newline: Optional[str], binary: bool, closefd: bool,
- encoding: Optional[str], errors: Optional[str],
- buffering: int, raw_io: bool, is_stream: bool = False):
- self.file_object = file_object
- self.file_path = file_path # type: ignore[var-annotated]
- self._append = append
- self._read = read
- self.allow_update = update
- self._closefd = closefd
- self._file_epoch = file_object.epoch
- self.raw_io = raw_io
- self._binary = binary
- self.is_stream = is_stream
- self._changed = False
- self._buffer_size = buffering
- if self._buffer_size == 0 and not binary:
- raise ValueError("can't have unbuffered text I/O")
- # buffer_size is ignored in text mode
- elif self._buffer_size == -1 or not binary:
- self._buffer_size = io.DEFAULT_BUFFER_SIZE
- self._use_line_buffer = not binary and buffering == 1
-
- contents = file_object.byte_contents
- self._encoding = encoding or locale.getpreferredencoding(False)
- errors = errors or 'strict'
- self._io: Union[BinaryBufferIO, TextBufferIO] = (
- BinaryBufferIO(contents) if binary
- else TextBufferIO(contents, encoding=encoding,
- newline=newline, errors=errors)
- )
- self._read_whence = 0
- self._read_seek = 0
- self._flush_pos = 0
- if contents:
- self._flush_pos = len(contents)
- if update:
- if not append:
- self._io.seek(0)
- else:
- self._io.seek(self._flush_pos)
- self._read_seek = self._io.tell()
-
- if delete_on_close:
- assert filesystem, 'delete_on_close=True requires filesystem'
- self._filesystem = filesystem
- self.delete_on_close = delete_on_close
- # override, don't modify FakeFile.name, as FakeFilesystem expects
- # it to be the file name only, no directories.
- self.name = file_object.opened_as
- self.filedes: Optional[int] = None
-
- def __enter__(self) -> 'FakeFileWrapper':
- """To support usage of this fake file with the 'with' statement."""
- return self
-
- def __exit__(self, exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType]
- ) -> None:
- """To support usage of this fake file with the 'with' statement."""
- self.close()
-
- def _raise(self, message: str) -> NoReturn:
- if self.raw_io:
- self._filesystem.raise_os_error(errno.EBADF, self.file_path)
- raise io.UnsupportedOperation(message)
-
- def get_object(self) -> FakeFile:
- """Return the FakeFile object that is wrapped by the current instance.
- """
- return self.file_object
-
- def fileno(self) -> int:
- """Return the file descriptor of the file object."""
- if self.filedes is not None:
- return self.filedes
- raise OSError(errno.EBADF, 'Invalid file descriptor')
-
- def close(self) -> None:
- """Close the file."""
- # ignore closing a closed file
- if not self._is_open():
- return
-
- # for raw io, all writes are flushed immediately
- if self.allow_update and not self.raw_io:
- self.flush()
- if self._filesystem.is_windows_fs and self._changed:
- self.file_object.st_mtime = now()
-
- assert self.filedes is not None
- if self._closefd:
- self._filesystem._close_open_file(self.filedes)
- else:
- open_files = self._filesystem.open_files[self.filedes]
- assert open_files is not None
- open_files.remove(self)
- if self.delete_on_close:
- self._filesystem.remove_object(
- self.get_object().path) # type: ignore[arg-type]
-
- @property
- def closed(self) -> bool:
- """Simulate the `closed` attribute on file."""
- return not self._is_open()
-
- def _try_flush(self, old_pos: int) -> None:
- """Try to flush and reset the position if it fails."""
- flush_pos = self._flush_pos
- try:
- self.flush()
- except OSError:
- # write failed - reset to previous position
- self._io.seek(old_pos)
- self._io.truncate()
- self._flush_pos = flush_pos
- raise
-
- def flush(self) -> None:
- """Flush file contents to 'disk'."""
- self._check_open_file()
- if self.allow_update and not self.is_stream:
- contents = self._io.getvalue()
- if self._append:
- self._sync_io()
- old_contents = self.file_object.byte_contents
- assert old_contents is not None
- contents = old_contents + contents[self._flush_pos:]
- self._set_stream_contents(contents)
- else:
- self._io.flush()
- changed = self.file_object.set_contents(contents, self._encoding)
- self.update_flush_pos()
- if changed:
- if self._filesystem.is_windows_fs:
- self._changed = True
- else:
- current_time = now()
- self.file_object.st_ctime = current_time
- self.file_object.st_mtime = current_time
- self._file_epoch = self.file_object.epoch
-
- if not self.is_stream:
- self._flush_related_files()
-
- def update_flush_pos(self) -> None:
- self._flush_pos = self._io.tell()
-
- def _flush_related_files(self) -> None:
- for open_files in self._filesystem.open_files[3:]:
- if open_files is not None:
- for open_file in open_files:
- if (open_file is not self and
- isinstance(open_file, FakeFileWrapper) and
- self.file_object == open_file.file_object and
- not open_file._append):
- open_file._sync_io()
-
- def seek(self, offset: int, whence: int = 0) -> None:
- """Move read/write pointer in 'file'."""
- self._check_open_file()
- if not self._append:
- self._io.seek(offset, whence)
- else:
- self._read_seek = offset
- self._read_whence = whence
- if not self.is_stream:
- self.flush()
-
- def tell(self) -> int:
- """Return the file's current position.
-
- Returns:
- int, file's current position in bytes.
- """
- self._check_open_file()
- if not self.is_stream:
- self.flush()
-
- if not self._append:
- return self._io.tell()
- if self._read_whence:
- write_seek = self._io.tell()
- self._io.seek(self._read_seek, self._read_whence)
- self._read_seek = self._io.tell()
- self._read_whence = 0
- self._io.seek(write_seek)
- return self._read_seek
-
- def _sync_io(self) -> None:
- """Update the stream with changes to the file object contents."""
- if self._file_epoch == self.file_object.epoch:
- return
-
- contents = self.file_object.byte_contents
- assert contents is not None
- self._set_stream_contents(contents)
- self._file_epoch = self.file_object.epoch
-
- def _set_stream_contents(self, contents: bytes) -> None:
- whence = self._io.tell()
- self._io.seek(0)
- self._io.truncate()
- self._io.putvalue(contents)
- if not self._append:
- self._io.seek(whence)
-
- def _read_wrappers(self, name: str) -> Callable:
- """Wrap a stream attribute in a read wrapper.
-
- Returns a read_wrapper which tracks our own read pointer since the
- stream object has no concept of a different read and write pointer.
-
- Args:
- name: The name of the attribute to wrap. Should be a read call.
-
- Returns:
- The read_wrapper function.
- """
- io_attr = getattr(self._io, name)
-
- def read_wrapper(*args, **kwargs):
- """Wrap all read calls to the stream object.
-
- We do this to track the read pointer separate from the write
- pointer. Anything that wants to read from the stream object
- while we're in append mode goes through this.
-
- Args:
- *args: pass through args
- **kwargs: pass through kwargs
- Returns:
- Wrapped stream object method
- """
- self._io.seek(self._read_seek, self._read_whence)
- ret_value = io_attr(*args, **kwargs)
- self._read_seek = self._io.tell()
- self._read_whence = 0
- self._io.seek(0, 2)
- return ret_value
-
- return read_wrapper
-
- def _other_wrapper(self, name: str) -> Callable:
- """Wrap a stream attribute in an other_wrapper.
-
- Args:
- name: the name of the stream attribute to wrap.
-
- Returns:
- other_wrapper which is described below.
- """
- io_attr = getattr(self._io, name)
-
- def other_wrapper(*args, **kwargs):
- """Wrap all other calls to the stream Object.
-
- We do this to track changes to the write pointer. Anything that
- moves the write pointer in a file open for appending should move
- the read pointer as well.
-
- Args:
- *args: Pass through args.
- **kwargs: Pass through kwargs.
-
- Returns:
- Wrapped stream object method.
- """
- write_seek = self._io.tell()
- ret_value = io_attr(*args, **kwargs)
- if write_seek != self._io.tell():
- self._read_seek = self._io.tell()
- self._read_whence = 0
-
- return ret_value
-
- return other_wrapper
-
- def _write_wrapper(self, name: str) -> Callable:
- """Wrap a stream attribute in a write_wrapper.
-
- Args:
- name: the name of the stream attribute to wrap.
-
- Returns:
- write_wrapper which is described below.
- """
- io_attr = getattr(self._io, name)
-
- def write_wrapper(*args, **kwargs):
- """Wrap all other calls to the stream Object.
-
- We do this to track changes to the write pointer. Anything that
- moves the write pointer in a file open for appending should move
- the read pointer as well.
-
- Args:
- *args: Pass through args.
- **kwargs: Pass through kwargs.
-
- Returns:
- Wrapped stream object method.
- """
- old_pos = self._io.tell()
- ret_value = io_attr(*args, **kwargs)
- new_pos = self._io.tell()
-
- # if the buffer size is exceeded, we flush
- use_line_buf = self._use_line_buffer and '\n' in args[0]
- if new_pos - self._flush_pos > self._buffer_size or use_line_buf:
- flush_all = (new_pos - old_pos > self._buffer_size or
- use_line_buf)
- # if the current write does not exceed the buffer size,
- # we revert to the previous position and flush that,
- # otherwise we flush all
- if not flush_all:
- self._io.seek(old_pos)
- self._io.truncate()
- self._try_flush(old_pos)
- if not flush_all:
- ret_value = io_attr(*args, **kwargs)
- if self._append:
- self._read_seek = self._io.tell()
- self._read_whence = 0
- return ret_value
-
- return write_wrapper
-
- def _adapt_size_for_related_files(self, size: int) -> None:
- for open_files in self._filesystem.open_files[3:]:
- if open_files is not None:
- for open_file in open_files:
- if (open_file is not self and
- isinstance(open_file, FakeFileWrapper) and
- self.file_object == open_file.file_object and
- cast(FakeFileWrapper, open_file)._append):
- open_file._read_seek += size
-
- def _truncate_wrapper(self) -> Callable:
- """Wrap truncate() to allow flush after truncate.
-
- Returns:
- Wrapper which is described below.
- """
- io_attr = getattr(self._io, 'truncate')
-
- def truncate_wrapper(*args, **kwargs):
- """Wrap truncate call to call flush after truncate."""
- if self._append:
- self._io.seek(self._read_seek, self._read_whence)
- size = io_attr(*args, **kwargs)
- self.flush()
- if not self.is_stream:
- self.file_object.size = size
- buffer_size = len(self._io.getvalue())
- if buffer_size < size:
- self._io.seek(buffer_size)
- self._io.putvalue(b'\0' * (size - buffer_size))
- self.file_object.set_contents(
- self._io.getvalue(), self._encoding)
- self._flush_pos = size
- self._adapt_size_for_related_files(size - buffer_size)
-
- self.flush()
- return size
-
- return truncate_wrapper
-
- def size(self) -> int:
- """Return the content size in bytes of the wrapped file."""
- return self.file_object.st_size
-
- def __getattr__(self, name: str) -> Any:
- if self.file_object.is_large_file():
- raise FakeLargeFileIoException(self.file_path)
-
- reading = name.startswith('read') or name == 'next'
- truncate = name == 'truncate'
- writing = name.startswith('write') or truncate
-
- if reading or writing:
- self._check_open_file()
- if not self._read and reading:
- return self._read_error()
- if not self.allow_update and writing:
- return self._write_error()
-
- if reading:
- self._sync_io()
- if not self.is_stream:
- self.flush()
- if not self._filesystem.is_windows_fs:
- self.file_object.st_atime = now()
- if truncate:
- return self._truncate_wrapper()
- if self._append:
- if reading:
- return self._read_wrappers(name)
- elif not writing:
- return self._other_wrapper(name)
- if writing:
- return self._write_wrapper(name)
-
- return getattr(self._io, name)
-
- def _read_error(self) -> Callable:
- def read_error(*args, **kwargs):
- """Throw an error unless the argument is zero."""
- if args and args[0] == 0:
- if self._filesystem.is_windows_fs and self.raw_io:
- return b'' if self._binary else u''
- self._raise('File is not open for reading.')
-
- return read_error
-
- def _write_error(self) -> Callable:
- def write_error(*args, **kwargs):
- """Throw an error."""
- if self.raw_io:
- if (self._filesystem.is_windows_fs and args
- and len(args[0]) == 0):
- return 0
- self._raise('File is not open for writing.')
-
- return write_error
-
- def _is_open(self) -> bool:
- if (self.filedes is not None and
- self.filedes < len(self._filesystem.open_files)):
- open_files = self._filesystem.open_files[self.filedes]
- if open_files is not None and self in open_files:
- return True
- return False
-
- def _check_open_file(self) -> None:
- if not self.is_stream and not self._is_open():
- raise ValueError('I/O operation on closed file')
-
- def __iter__(self) -> Union[Iterator[str], Iterator[bytes]]:
- if not self._read:
- self._raise('File is not open for reading')
- return self._io.__iter__()
-
- def __next__(self):
- if not self._read:
- self._raise('File is not open for reading')
- return next(self._io)
-
-
-class StandardStreamWrapper:
- """Wrapper for a system standard stream to be used in open files list.
- """
-
- def __init__(self, stream_object: TextIO):
- self._stream_object = stream_object
- self.filedes: Optional[int] = None
-
- def get_object(self) -> TextIO:
- return self._stream_object
-
- def fileno(self) -> int:
- """Return the file descriptor of the wrapped standard stream."""
- if self.filedes is not None:
- return self.filedes
- raise OSError(errno.EBADF, 'Invalid file descriptor')
-
- def read(self, n: int = -1) -> bytes:
- return cast(bytes, self._stream_object.read())
-
- def close(self) -> None:
- """We do not support closing standard streams."""
- pass
-
- def is_stream(self) -> bool:
- return True
-
-
-class FakeDirWrapper:
- """Wrapper for a FakeDirectory object to be used in open files list.
- """
-
- def __init__(self, file_object: FakeDirectory,
- file_path: AnyString, filesystem: FakeFilesystem):
- self.file_object = file_object
- self.file_path = file_path
- self._filesystem = filesystem
- self.filedes: Optional[int] = None
-
- def get_object(self) -> FakeDirectory:
- """Return the FakeFile object that is wrapped by the current instance.
- """
- return self.file_object
-
- def fileno(self) -> int:
- """Return the file descriptor of the file object."""
- if self.filedes is not None:
- return self.filedes
- raise OSError(errno.EBADF, 'Invalid file descriptor')
-
- def close(self) -> None:
- """Close the directory."""
- assert self.filedes is not None
- self._filesystem._close_open_file(self.filedes)
-
-
-class FakePipeWrapper:
- """Wrapper for a read or write descriptor of a real pipe object to be
- used in open files list.
- """
-
- def __init__(self, filesystem: FakeFilesystem,
- fd: int, can_write: bool, mode: str = ''):
- self._filesystem = filesystem
- self.fd = fd # the real file descriptor
- self.can_write = can_write
- self.file_object = None
- self.filedes: Optional[int] = None
- self.real_file = None
- if mode:
- self.real_file = open(fd, mode)
-
- def __enter__(self) -> 'FakePipeWrapper':
- """To support usage of this fake pipe with the 'with' statement."""
- return self
-
- def __exit__(self, exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType]
- ) -> None:
- """To support usage of this fake pipe with the 'with' statement."""
- self.close()
-
- def get_object(self) -> None:
- return self.file_object
-
- def fileno(self) -> int:
- """Return the fake file descriptor of the pipe object."""
- if self.filedes is not None:
- return self.filedes
- raise OSError(errno.EBADF, 'Invalid file descriptor')
-
- def read(self, numBytes: int = -1) -> bytes:
- """Read from the real pipe."""
- if self.real_file:
- return self.real_file.read(numBytes)
- return os.read(self.fd, numBytes)
-
- def flush(self) -> None:
- """Flush the real pipe?"""
- pass
-
- def write(self, contents: bytes) -> int:
- """Write to the real pipe."""
- if self.real_file:
- return self.real_file.write(contents)
- return os.write(self.fd, contents)
-
- def close(self) -> None:
- """Close the pipe descriptor."""
- assert self.filedes is not None
- open_files = self._filesystem.open_files[self.filedes]
- assert open_files is not None
- open_files.remove(self)
- if self.real_file:
- self.real_file.close()
- else:
- os.close(self.fd)
-
- def readable(self) -> bool:
- """The pipe end can either be readable or writable."""
- return not self.can_write
-
- def writable(self) -> bool:
- """The pipe end can either be readable or writable."""
- return self.can_write
-
- def seekable(self) -> bool:
- """A pipe is not seekable."""
- return False
-
-
-Deprecator.add(FakeFileWrapper, FakeFileWrapper.get_object, 'GetObject')
-Deprecator.add(FakeFileWrapper, FakeFileWrapper.size, 'Size')
-
-
-class FakeFileOpen:
- """Faked `file()` and `open()` function replacements.
-
- Returns FakeFile objects in a FakeFilesystem in place of the `file()`
- or `open()` function.
- """
- __name__ = 'FakeFileOpen'
-
- def __init__(self, filesystem: FakeFilesystem,
- delete_on_close: bool = False, raw_io: bool = False):
- """
- Args:
- filesystem: FakeFilesystem used to provide file system information
- delete_on_close: optional boolean, deletes file on close()
- """
- self.filesystem = filesystem
- self._delete_on_close = delete_on_close
- self.raw_io = raw_io
-
- def __call__(self, *args: Any, **kwargs: Any) -> AnyFileWrapper:
- """Redirects calls to file() or open() to appropriate method."""
- return self.call(*args, **kwargs)
-
- def call(self, file_: Union[AnyStr, int],
- mode: str = 'r',
- buffering: int = -1,
- encoding: Optional[str] = None,
- errors: Optional[str] = None,
- newline: Optional[str] = None,
- closefd: bool = True,
- opener: Any = None,
- open_modes: Optional[_OpenModes] = None) -> AnyFileWrapper:
- """Return a file-like object with the contents of the target
- file object.
-
- Args:
- file_: Path to target file or a file descriptor.
- mode: Additional file modes (all modes in `open()` are supported).
- buffering: the buffer size used for writing. Data will only be
- flushed if buffer size is exceeded. The default (-1) uses a
- system specific default buffer size. Text line mode (e.g.
- buffering=1 in text mode) is not supported.
- encoding: The encoding used to encode unicode strings / decode
- bytes.
- errors: (str) Defines how encoding errors are handled.
- newline: Controls universal newlines, passed to stream object.
- closefd: If a file descriptor rather than file name is passed,
- and this is set to `False`, then the file descriptor is kept
- open when file is closed.
- opener: not supported.
- open_modes: Modes for opening files if called from low-level API.
-
- Returns:
- A file-like object containing the contents of the target file.
-
- Raises:
- OSError depending on Python version / call mode:
- - if the target object is a directory
- - on an invalid path
- - if the file does not exist when it should
- - if the file exists but should not
- - if permission is denied
- ValueError: for an invalid mode or mode combination
- """
- binary = 'b' in mode
-
- if binary and encoding:
- raise ValueError("binary mode doesn't take an encoding argument")
-
- newline, open_modes = self._handle_file_mode(mode, newline, open_modes)
-
- file_object, file_path, filedes, real_path = self._handle_file_arg(
- file_)
- if file_object is None and file_path is None:
- # file must be a fake pipe wrapper, find it...
- if (filedes is None or
- len(self.filesystem.open_files) <= filedes or
- not self.filesystem.open_files[filedes]):
- raise OSError(errno.EBADF, 'invalid pipe file descriptor')
- wrappers = self.filesystem.open_files[filedes]
- assert wrappers is not None
- existing_wrapper = wrappers[0]
- assert isinstance(existing_wrapper, FakePipeWrapper)
- wrapper = FakePipeWrapper(self.filesystem, existing_wrapper.fd,
- existing_wrapper.can_write, mode)
- file_des = self.filesystem._add_open_file(wrapper)
- wrapper.filedes = file_des
- return wrapper
-
- assert file_path is not None
- if not filedes:
- closefd = True
-
- if (open_modes.must_not_exist and
- (file_object or self.filesystem.islink(file_path) and
- not self.filesystem.is_windows_fs)):
- self.filesystem.raise_os_error(errno.EEXIST, file_path)
-
- assert real_path is not None
- file_object = self._init_file_object(file_object,
- file_path, open_modes,
- real_path)
-
- if S_ISDIR(file_object.st_mode):
- if self.filesystem.is_windows_fs:
- self.filesystem.raise_os_error(errno.EACCES, file_path)
- else:
- self.filesystem.raise_os_error(errno.EISDIR, file_path)
-
- # If you print obj.name, the argument to open() must be printed.
- # Not the abspath, not the filename, but the actual argument.
- file_object.opened_as = file_path
- if open_modes.truncate:
- current_time = now()
- file_object.st_mtime = current_time
- if not self.filesystem.is_windows_fs:
- file_object.st_ctime = current_time
-
- fakefile = FakeFileWrapper(file_object,
- file_path,
- update=open_modes.can_write,
- read=open_modes.can_read,
- append=open_modes.append,
- delete_on_close=self._delete_on_close,
- filesystem=self.filesystem,
- newline=newline,
- binary=binary,
- closefd=closefd,
- encoding=encoding,
- errors=errors,
- buffering=buffering,
- raw_io=self.raw_io)
- if filedes is not None:
- fakefile.filedes = filedes
- # replace the file wrapper
- open_files_list = self.filesystem.open_files[filedes]
- assert open_files_list is not None
- open_files_list.append(fakefile)
- else:
- fakefile.filedes = self.filesystem._add_open_file(fakefile)
- return fakefile
-
- def _init_file_object(self, file_object: Optional[FakeFile],
- file_path: AnyStr,
- open_modes: _OpenModes,
- real_path: AnyString) -> FakeFile:
- if file_object:
- if (not is_root() and
- ((open_modes.can_read and
- not file_object.st_mode & PERM_READ)
- or (open_modes.can_write and
- not file_object.st_mode & PERM_WRITE))):
- self.filesystem.raise_os_error(errno.EACCES, file_path)
- if open_modes.can_write:
- if open_modes.truncate:
- file_object.set_contents('')
- else:
- if open_modes.must_exist:
- self.filesystem.raise_os_error(errno.ENOENT, file_path)
- if self.filesystem.islink(file_path):
- link_object = self.filesystem.resolve(file_path,
- follow_symlinks=False)
- assert link_object.contents is not None
- target_path = cast(AnyStr, link_object.contents)
- else:
- target_path = file_path
- if self.filesystem.ends_with_path_separator(target_path):
- error = (
- errno.EINVAL if self.filesystem.is_windows_fs
- else errno.ENOENT if self.filesystem.is_macos
- else errno.EISDIR
- )
- self.filesystem.raise_os_error(error, file_path)
- file_object = self.filesystem.create_file_internally(
- real_path, create_missing_dirs=False,
- apply_umask=True)
- return file_object
-
- def _handle_file_arg(self, file_: Union[AnyStr, int]) -> Tuple[
- Optional[FakeFile], Optional[AnyStr],
- Optional[int], Optional[AnyStr]]:
- file_object = None
- if isinstance(file_, int):
- # opening a file descriptor
- filedes: int = file_
- wrapper = self.filesystem.get_open_file(filedes)
- if isinstance(wrapper, FakePipeWrapper):
- return None, None, filedes, None
- if isinstance(wrapper, FakeFileWrapper):
- self._delete_on_close = wrapper.delete_on_close
- file_object = cast(FakeFile, self.filesystem.get_open_file(
- filedes).get_object())
- assert file_object is not None
- path = file_object.name
- return file_object, cast(AnyStr, path), filedes, cast(AnyStr, path)
-
- # open a file file by path
- file_path = cast(AnyStr, file_)
- if file_path == self.filesystem.dev_null.name:
- file_object = self.filesystem.dev_null
- real_path = file_path
- else:
- real_path = self.filesystem.resolve_path(file_path)
- if self.filesystem.exists(file_path):
- file_object = self.filesystem.get_object_from_normpath(
- real_path, check_read_perm=False)
- return file_object, file_path, None, real_path
-
- def _handle_file_mode(
- self, mode: str,
- newline: Optional[str],
- open_modes: Optional[_OpenModes]) -> Tuple[Optional[str],
- _OpenModes]:
- orig_modes = mode # Save original modes for error messages.
- # Normalize modes. Handle 't' and 'U'.
- if 'b' in mode and 't' in mode:
- raise ValueError('Invalid mode: ' + mode)
- mode = mode.replace('t', '').replace('b', '')
- mode = mode.replace('rU', 'r').replace('U', 'r')
- if not self.raw_io:
- if mode not in _OPEN_MODE_MAP:
- raise ValueError('Invalid mode: %r' % orig_modes)
- open_modes = _OpenModes(*_OPEN_MODE_MAP[mode])
- assert open_modes is not None
- return newline, open_modes
+ def _create_temp_dir(self):
+ # the temp directory is assumed to exist at least in `tempfile`,
+ # so we create it here for convenience
+ temp_dir = tempfile.gettempdir()
+ if not self.exists(temp_dir):
+ self.create_dir(temp_dir)
+ if sys.platform != "win32" and not self.exists("/tmp"):
+ # under Posix, we also create a link in /tmp if the path does not exist
+ self.create_symlink("/tmp", temp_dir)
+ # reset the used size to 0 to avoid having the link size counted
+ # which would make disk size tests more complicated
+ next(iter(self.mount_points.values()))["used_size"] = 0
def _run_doctest() -> TestResults:
import doctest
import pyfakefs
+
return doctest.testmod(pyfakefs.fake_filesystem)
-if __name__ == '__main__':
+def __getattr__(name):
+ # backwards compatibility for read access to globals moved to helpers
+ if name == "USER_ID":
+ return helpers.USER_ID
+ if name == "GROUP_ID":
+ return helpers.GROUP_ID
+ raise AttributeError(f"No attribute {name!r}.")
+
+
+if __name__ == "__main__":
_run_doctest()
diff --git a/pyfakefs/fake_filesystem_shutil.py b/pyfakefs/fake_filesystem_shutil.py
index 314e11b..561ccd2 100755
--- a/pyfakefs/fake_filesystem_shutil.py
+++ b/pyfakefs/fake_filesystem_shutil.py
@@ -26,12 +26,14 @@ work fine with the fake file system if `os`/`os.path` are patched.
`fake_filesystem_unittest.TestCase`, pytest fs fixture,
or directly `Patcher`.
"""
-
+import os
import shutil
+import sys
class FakeShutilModule:
- """Uses a FakeFilesystem to provide a fake replacement for shutil module.
+ """Uses a FakeFilesystem to provide a fake replacement
+ for shutil module.
"""
@staticmethod
@@ -39,7 +41,7 @@ class FakeShutilModule:
"""Return the list of patched function names. Used for patching
functions imported from the module.
"""
- return 'disk_usage',
+ return ("disk_usage",)
def __init__(self, filesystem):
"""Construct fake shutil module using the fake filesystem.
@@ -59,6 +61,49 @@ class FakeShutilModule:
"""
return self.filesystem.get_disk_usage(path)
+ if sys.version_info >= (3, 12) and sys.platform == "win32":
+
+ def copy2(self, src, dst, *, follow_symlinks=True):
+ """Since Python 3.12, there is an optimization fow Windows,
+ using the Windows API. We just remove this and fall back to the previous
+ implementation.
+ """
+ if self.filesystem.isdir(dst):
+ dst = self.filesystem.joinpaths(dst, os.path.basename(src))
+
+ self.copyfile(src, dst, follow_symlinks=follow_symlinks)
+ self.copystat(src, dst, follow_symlinks=follow_symlinks)
+ return dst
+
+ def copytree(
+ self,
+ src,
+ dst,
+ symlinks=False,
+ ignore=None,
+ copy_function=shutil.copy2,
+ ignore_dangling_symlinks=False,
+ dirs_exist_ok=False,
+ ):
+ """Make sure the default argument is patched."""
+ if copy_function == shutil.copy2:
+ copy_function = self.copy2
+ return self._shutil_module.copytree(
+ src,
+ dst,
+ symlinks,
+ ignore,
+ copy_function,
+ ignore_dangling_symlinks,
+ dirs_exist_ok,
+ )
+
+ def move(self, src, dst, copy_function=shutil.copy2):
+ """Make sure the default argument is patched."""
+ if copy_function == shutil.copy2:
+ copy_function = self.copy2
+ return self._shutil_module.move(src, dst, copy_function)
+
def __getattr__(self, name):
"""Forwards any non-faked calls to the standard shutil module."""
return getattr(self._shutil_module, name)
diff --git a/pyfakefs/fake_filesystem_unittest.py b/pyfakefs/fake_filesystem_unittest.py
index 6633cb5..4604a65 100644
--- a/pyfakefs/fake_filesystem_unittest.py
+++ b/pyfakefs/fake_filesystem_unittest.py
@@ -35,10 +35,15 @@ Existing unit tests that use the real file system can be retrofitted to use
pyfakefs by simply changing their base class from `:py:class`unittest.TestCase`
to `:py:class`pyfakefs.fake_filesystem_unittest.TestCase`.
"""
+import _io # type:ignore[import]
+import builtins
import doctest
import functools
+import genericpath
import inspect
+import io
import linecache
+import os
import shutil
import sys
import tempfile
@@ -46,28 +51,38 @@ import tokenize
from importlib.abc import Loader, MetaPathFinder
from types import ModuleType, TracebackType, FunctionType
from typing import (
- Any, Callable, Dict, List, Set, Tuple, Optional, Union,
- AnyStr, Type, Iterator, cast, ItemsView, Sequence
+ Any,
+ Callable,
+ Dict,
+ List,
+ Set,
+ Tuple,
+ Optional,
+ Union,
+ Type,
+ Iterator,
+ cast,
+ ItemsView,
+ Sequence,
)
import unittest
import warnings
from unittest import TestSuite
-from pyfakefs.deprecator import Deprecator
from pyfakefs.fake_filesystem import (
- set_uid, set_gid, reset_ids, PatchMode, FakeFile, FakeFilesystem
+ set_uid,
+ set_gid,
+ reset_ids,
+ PatchMode,
+ FakeFilesystem,
)
from pyfakefs.helpers import IS_PYPY
from pyfakefs.mox3_stubout import StubOutForTesting
-try:
- from importlib.machinery import ModuleSpec
-except ImportError:
- ModuleSpec = object # type: ignore[assignment, misc]
-
+from importlib.machinery import ModuleSpec
from importlib import reload
-from pyfakefs import fake_filesystem
+from pyfakefs import fake_filesystem, fake_io, fake_os, fake_open, fake_path, fake_file
from pyfakefs import fake_filesystem_shutil
from pyfakefs import fake_pathlib
from pyfakefs import mox3_stubout
@@ -76,20 +91,22 @@ from pyfakefs.extra_packages import pathlib2, use_scandir
if use_scandir:
from pyfakefs import fake_scandir
-OS_MODULE = 'nt' if sys.platform == 'win32' else 'posix'
-PATH_MODULE = 'ntpath' if sys.platform == 'win32' else 'posixpath'
-
-
-def patchfs(_func: Callable = None, *,
- additional_skip_names: Optional[
- List[Union[str, ModuleType]]] = None,
- modules_to_reload: Optional[List[ModuleType]] = None,
- modules_to_patch: Optional[Dict[str, ModuleType]] = None,
- allow_root_user: bool = True,
- use_known_patches: bool = True,
- patch_open_code: PatchMode = PatchMode.OFF,
- patch_default_args: bool = False,
- use_cache: bool = True) -> Callable:
+OS_MODULE = "nt" if sys.platform == "win32" else "posix"
+PATH_MODULE = "ntpath" if sys.platform == "win32" else "posixpath"
+
+
+def patchfs(
+ _func: Optional[Callable] = None,
+ *,
+ additional_skip_names: Optional[List[Union[str, ModuleType]]] = None,
+ modules_to_reload: Optional[List[ModuleType]] = None,
+ modules_to_patch: Optional[Dict[str, ModuleType]] = None,
+ allow_root_user: bool = True,
+ use_known_patches: bool = True,
+ patch_open_code: PatchMode = PatchMode.OFF,
+ patch_default_args: bool = False,
+ use_cache: bool = True
+) -> Callable:
"""Convenience decorator to use patcher with additional parameters in a
test function.
@@ -108,14 +125,15 @@ def patchfs(_func: Callable = None, *,
@functools.wraps(f)
def wrapped(*args, **kwargs):
with Patcher(
- additional_skip_names=additional_skip_names,
- modules_to_reload=modules_to_reload,
- modules_to_patch=modules_to_patch,
- allow_root_user=allow_root_user,
- use_known_patches=use_known_patches,
- patch_open_code=patch_open_code,
- patch_default_args=patch_default_args,
- use_cache=use_cache) as p:
+ additional_skip_names=additional_skip_names,
+ modules_to_reload=modules_to_reload,
+ modules_to_patch=modules_to_patch,
+ allow_root_user=allow_root_user,
+ use_known_patches=use_known_patches,
+ patch_open_code=patch_open_code,
+ patch_default_args=patch_default_args,
+ use_cache=use_cache,
+ ) as p:
args = list(args)
args.append(p.fs)
return f(*args, **kwargs)
@@ -128,23 +146,28 @@ def patchfs(_func: Callable = None, *,
"Decorator argument is not a function.\n"
"Did you mean `@patchfs(additional_skip_names=...)`?"
)
- if hasattr(_func, 'patchings'):
+ if hasattr(_func, "patchings"):
_func.nr_patches = len(_func.patchings) # type: ignore
return wrap_patchfs(_func)
return wrap_patchfs
+DOCTEST_PATCHER = None
+
+
def load_doctests(
- loader: Any, tests: TestSuite, ignore: Any, module: ModuleType,
- additional_skip_names: Optional[
- List[Union[str, ModuleType]]] = None,
- modules_to_reload: Optional[List[ModuleType]] = None,
- modules_to_patch: Optional[Dict[str, ModuleType]] = None,
- allow_root_user: bool = True,
- use_known_patches: bool = True,
- patch_open_code: PatchMode = PatchMode.OFF,
- patch_default_args: bool = False
+ loader: Any,
+ tests: TestSuite,
+ ignore: Any,
+ module: ModuleType,
+ additional_skip_names: Optional[List[Union[str, ModuleType]]] = None,
+ modules_to_reload: Optional[List[ModuleType]] = None,
+ modules_to_patch: Optional[Dict[str, ModuleType]] = None,
+ allow_root_user: bool = True,
+ use_known_patches: bool = True,
+ patch_open_code: PatchMode = PatchMode.OFF,
+ patch_default_args: bool = False,
) -> TestSuite: # pylint:disable=unused-argument
"""Load the doctest tests for the specified module into unittest.
Args:
@@ -154,18 +177,28 @@ def load_doctests(
File `example_test.py` in the pyfakefs release provides a usage example.
"""
- _patcher = Patcher(additional_skip_names=additional_skip_names,
- modules_to_reload=modules_to_reload,
- modules_to_patch=modules_to_patch,
- allow_root_user=allow_root_user,
- use_known_patches=use_known_patches,
- patch_open_code=patch_open_code,
- patch_default_args=patch_default_args)
- globs = _patcher.replace_globs(vars(module))
- tests.addTests(doctest.DocTestSuite(module,
- globs=globs,
- setUp=_patcher.setUp,
- tearDown=_patcher.tearDown))
+ has_patcher = Patcher.DOC_PATCHER is not None
+ if not has_patcher:
+ Patcher.DOC_PATCHER = Patcher(
+ additional_skip_names=additional_skip_names,
+ modules_to_reload=modules_to_reload,
+ modules_to_patch=modules_to_patch,
+ allow_root_user=allow_root_user,
+ use_known_patches=use_known_patches,
+ patch_open_code=patch_open_code,
+ patch_default_args=patch_default_args,
+ is_doc_test=True,
+ )
+ assert Patcher.DOC_PATCHER is not None
+ globs = Patcher.DOC_PATCHER.replace_globs(vars(module))
+ tests.addTests(
+ doctest.DocTestSuite(
+ module,
+ globs=globs,
+ setUp=Patcher.DOC_PATCHER.setUp,
+ tearDown=Patcher.DOC_PATCHER.tearDown,
+ )
+ )
return tests
@@ -214,19 +247,26 @@ class TestCaseMixin:
modules_to_patch: Optional[Dict[str, ModuleType]] = None
@property
+ def patcher(self):
+ if hasattr(self, "_patcher"):
+ return self._patcher or Patcher.PATCHER
+ return Patcher.PATCHER
+
+ @property
def fs(self) -> FakeFilesystem:
- return cast(FakeFilesystem, self._stubber.fs)
-
- def setUpPyfakefs(self,
- additional_skip_names: Optional[
- List[Union[str, ModuleType]]] = None,
- modules_to_reload: Optional[List[ModuleType]] = None,
- modules_to_patch: Optional[Dict[str, ModuleType]] = None,
- allow_root_user: bool = True,
- use_known_patches: bool = True,
- patch_open_code: PatchMode = PatchMode.OFF,
- patch_default_args: bool = False,
- use_cache: bool = True) -> None:
+ return cast(FakeFilesystem, self.patcher.fs)
+
+ def setUpPyfakefs(
+ self,
+ additional_skip_names: Optional[List[Union[str, ModuleType]]] = None,
+ modules_to_reload: Optional[List[ModuleType]] = None,
+ modules_to_patch: Optional[Dict[str, ModuleType]] = None,
+ allow_root_user: bool = True,
+ use_known_patches: bool = True,
+ patch_open_code: PatchMode = PatchMode.OFF,
+ patch_default_args: bool = False,
+ use_cache: bool = True,
+ ) -> None:
"""Bind the file-related modules to the :py:class:`pyfakefs` fake file
system instead of the real file system. Also bind the fake `open()`
function.
@@ -238,13 +278,68 @@ class TestCaseMixin:
the current test case. Settings the arguments here may be a more
convenient way to adapt the setting than overwriting `__init__()`.
"""
+ # if the class has already a patcher setup, we use this one
+ if Patcher.PATCHER is not None:
+ return
+
if additional_skip_names is None:
additional_skip_names = self.additional_skip_names
if modules_to_reload is None:
modules_to_reload = self.modules_to_reload
if modules_to_patch is None:
modules_to_patch = self.modules_to_patch
- self._stubber = Patcher(
+ self._patcher = Patcher(
+ additional_skip_names=additional_skip_names,
+ modules_to_reload=modules_to_reload,
+ modules_to_patch=modules_to_patch,
+ allow_root_user=allow_root_user,
+ use_known_patches=use_known_patches,
+ patch_open_code=patch_open_code,
+ patch_default_args=patch_default_args,
+ use_cache=use_cache,
+ )
+
+ self._patcher.setUp()
+ cast(TestCase, self).addCleanup(self._patcher.tearDown)
+
+ @classmethod
+ def setUpClassPyfakefs(
+ cls,
+ additional_skip_names: Optional[List[Union[str, ModuleType]]] = None,
+ modules_to_reload: Optional[List[ModuleType]] = None,
+ modules_to_patch: Optional[Dict[str, ModuleType]] = None,
+ allow_root_user: bool = True,
+ use_known_patches: bool = True,
+ patch_open_code: PatchMode = PatchMode.OFF,
+ patch_default_args: bool = False,
+ use_cache: bool = True,
+ ) -> None:
+ """Similar to :py:func:`setUpPyfakefs`, but as a class method that
+ can be used in `setUpClass` instead of in `setUp`.
+ The fake filesystem will live in all test methods in the test class
+ and can be used in the usual way.
+ Note that using both :py:func:`setUpClassPyfakefs` and
+ :py:func:`setUpPyfakefs` in the same class will not work correctly.
+
+ .. note:: This method is only available from Python 3.8 onwards.
+ """
+ if sys.version_info < (3, 8):
+ raise NotImplementedError(
+ "setUpClassPyfakefs is only available in "
+ "Python versions starting from 3.8"
+ )
+
+ # if the class has already a patcher setup, we use this one
+ if Patcher.PATCHER is not None:
+ return
+
+ if additional_skip_names is None:
+ additional_skip_names = cls.additional_skip_names
+ if modules_to_reload is None:
+ modules_to_reload = cls.modules_to_reload
+ if modules_to_patch is None:
+ modules_to_patch = cls.modules_to_patch
+ Patcher.PATCHER = Patcher(
additional_skip_names=additional_skip_names,
modules_to_reload=modules_to_reload,
modules_to_patch=modules_to_patch,
@@ -252,11 +347,21 @@ class TestCaseMixin:
use_known_patches=use_known_patches,
patch_open_code=patch_open_code,
patch_default_args=patch_default_args,
- use_cache=use_cache
+ use_cache=use_cache,
)
- self._stubber.setUp()
- cast(TestCase, self).addCleanup(self._stubber.tearDown)
+ Patcher.PATCHER.setUp()
+ cast(TestCase, cls).addClassCleanup(Patcher.PATCHER.tearDown)
+
+ @classmethod
+ def fake_fs(cls):
+ """Convenience class method for accessing the fake filesystem.
+ For use inside `setUpClass`, after :py:func:`setUpClassPyfakefs`
+ has been called.
+ """
+ if Patcher.PATCHER:
+ return Patcher.PATCHER.fs
+ return None
def pause(self) -> None:
"""Pause the patching of the file system modules until `resume` is
@@ -265,7 +370,7 @@ class TestCaseMixin:
Calling pause() twice is silently ignored.
"""
- self._stubber.pause()
+ self.patcher.pause()
def resume(self) -> None:
"""Resume the patching of the file system modules if `pause` has
@@ -273,7 +378,7 @@ class TestCaseMixin:
executed in the fake file system.
Does nothing if patching is not paused.
"""
- self._stubber.resume()
+ self.patcher.resume()
class TestCase(unittest.TestCase, TestCaseMixin):
@@ -283,11 +388,13 @@ class TestCase(unittest.TestCase, TestCaseMixin):
The arguments are explained in :py:class:`TestCaseMixin`.
"""
- def __init__(self, methodName: str = 'runTest',
- additional_skip_names: Optional[
- List[Union[str, ModuleType]]] = None,
- modules_to_reload: Optional[List[ModuleType]] = None,
- modules_to_patch: Optional[Dict[str, ModuleType]] = None):
+ def __init__(
+ self,
+ methodName: str = "runTest",
+ additional_skip_names: Optional[List[Union[str, ModuleType]]] = None,
+ modules_to_reload: Optional[List[ModuleType]] = None,
+ modules_to_patch: Optional[Dict[str, ModuleType]] = None,
+ ):
"""Creates the test class instance and the patcher used to stub out
file system related modules.
@@ -301,53 +408,10 @@ class TestCase(unittest.TestCase, TestCaseMixin):
self.modules_to_reload = modules_to_reload
self.modules_to_patch = modules_to_patch
- @Deprecator('add_real_file')
- def copyRealFile(self, real_file_path: AnyStr,
- fake_file_path: Optional[AnyStr] = None,
- create_missing_dirs: bool = True) -> FakeFile:
- """Add the file `real_file_path` in the real file system to the same
- path in the fake file system.
-
- **This method is deprecated** in favor of
- :py:meth:`FakeFilesystem..add_real_file`.
- `copyRealFile()` is retained with limited functionality for backward
- compatibility only.
-
- Args:
- real_file_path: Path to the file in both the real and fake
- file systems
- fake_file_path: Deprecated. Use the default, which is
- `real_file_path`.
- If a value other than `real_file_path` is specified, a `ValueError`
- exception will be raised.
- create_missing_dirs: Deprecated. Use the default, which creates
- missing directories in the fake file system. If `False` is
- specified, a `ValueError` exception is raised.
-
- Returns:
- The newly created FakeFile object.
-
- Raises:
- OSError: If the file already exists in the fake file system.
- ValueError: If deprecated argument values are specified.
-
- See:
- :py:meth:`FakeFileSystem.add_real_file`
- """
- if fake_file_path is not None and real_file_path != fake_file_path:
- raise ValueError("CopyRealFile() is deprecated and no longer "
- "supports different real and fake file paths")
- if not create_missing_dirs:
- raise ValueError("CopyRealFile() is deprecated and no longer "
- "supports NOT creating missing directories")
- assert self._stubber.fs is not None
- return self._stubber.fs.add_real_file(real_file_path, read_only=False)
-
def tearDownPyfakefs(self) -> None:
"""This method is deprecated and exists only for backward
compatibility. It does nothing.
"""
- pass
class Patcher:
@@ -363,21 +427,49 @@ class Patcher:
with Patcher():
doStuff()
"""
- '''Stub nothing that is imported within these modules.
+
+ """Stub nothing that is imported within these modules.
`sys` is included to prevent `sys.path` from being stubbed with the fake
`os.path`.
- The `pytest` and `py` modules are used by pytest and have to access the
- real file system.
The `linecache` module is used to read the test file in case of test
failure to get traceback information before test tear down.
In order to make sure that reading the test file is not faked,
we skip faking the module.
We also have to set back the cached open function in tokenize.
- '''
+ """
SKIPMODULES = {
- None, fake_filesystem, fake_filesystem_shutil,
- sys, linecache, tokenize
+ None,
+ fake_filesystem,
+ fake_filesystem_shutil,
+ fake_os,
+ fake_io,
+ fake_open,
+ fake_path,
+ fake_file,
+ sys,
+ linecache,
+ tokenize,
+ os,
+ io,
+ _io,
+ genericpath,
+ os.path,
}
+ if sys.platform == "win32":
+ import nt # type:ignore[import]
+ import ntpath
+
+ SKIPMODULES.add(nt)
+ SKIPMODULES.add(ntpath)
+ else:
+ import posix
+ import posixpath
+ import fcntl
+
+ SKIPMODULES.add(posix)
+ SKIPMODULES.add(posixpath)
+ SKIPMODULES.add(fcntl)
+
# caches all modules that do not have file system modules or function
# to speed up _find_modules
CACHED_MODULES: Set[ModuleType] = set()
@@ -386,28 +478,42 @@ class Patcher:
FS_DEFARGS: List[Tuple[FunctionType, int, Callable[..., Any]]] = []
SKIPPED_FS_MODULES: Dict[str, Set[Tuple[ModuleType, str]]] = {}
- assert None in SKIPMODULES, ("sys.modules contains 'None' values;"
- " must skip them.")
+ assert None in SKIPMODULES, "sys.modules contains 'None' values;" " must skip them."
- IS_WINDOWS = sys.platform in ('win32', 'cygwin')
+ IS_WINDOWS = sys.platform in ("win32", "cygwin")
- SKIPNAMES = {'os', 'path', 'io', 'genericpath', 'fcntl',
- OS_MODULE, PATH_MODULE}
+ SKIPNAMES: Set[str] = set()
# hold values from last call - if changed, the cache has to be invalidated
PATCHED_MODULE_NAMES: Set[str] = set()
ADDITIONAL_SKIP_NAMES: Set[str] = set()
PATCH_DEFAULT_ARGS = False
-
- def __init__(self, additional_skip_names: Optional[
- List[Union[str, ModuleType]]] = None,
- modules_to_reload: Optional[List[ModuleType]] = None,
- modules_to_patch: Optional[Dict[str, ModuleType]] = None,
- allow_root_user: bool = True,
- use_known_patches: bool = True,
- patch_open_code: PatchMode = PatchMode.OFF,
- patch_default_args: bool = False,
- use_cache: bool = True) -> None:
+ PATCHER: Optional["Patcher"] = None
+ DOC_PATCHER: Optional["Patcher"] = None
+ REF_COUNT = 0
+ DOC_REF_COUNT = 0
+
+ def __new__(cls, *args, **kwargs):
+ if kwargs.get("is_doc_test", False):
+ if cls.DOC_PATCHER is None:
+ cls.DOC_PATCHER = super().__new__(cls)
+ return cls.DOC_PATCHER
+ if cls.PATCHER is None:
+ cls.PATCHER = super().__new__(cls)
+ return cls.PATCHER
+
+ def __init__(
+ self,
+ additional_skip_names: Optional[List[Union[str, ModuleType]]] = None,
+ modules_to_reload: Optional[List[ModuleType]] = None,
+ modules_to_patch: Optional[Dict[str, ModuleType]] = None,
+ allow_root_user: bool = True,
+ use_known_patches: bool = True,
+ patch_open_code: PatchMode = PatchMode.OFF,
+ patch_default_args: bool = False,
+ use_cache: bool = True,
+ is_doc_test: bool = False,
+ ) -> None:
"""
Args:
additional_skip_names: names of modules inside of which no module
@@ -439,7 +545,12 @@ class Patcher:
feature, this argument allows to turn it off in case it
causes any problems.
"""
-
+ self.is_doc_test = is_doc_test
+ if is_doc_test:
+ if self.DOC_REF_COUNT > 0:
+ return
+ elif self.REF_COUNT > 0:
+ return
if not allow_root_user:
# set non-root IDs even if the real user is root
set_uid(1)
@@ -449,11 +560,12 @@ class Patcher:
# save the original open function for use in pytest plugin
self.original_open = open
self.patch_open_code = patch_open_code
+ self.fake_open: fake_open.FakeFileOpen
if additional_skip_names is not None:
skip_names = [
- cast(ModuleType, m).__name__ if inspect.ismodule(m)
- else cast(str, m) for m in additional_skip_names
+ cast(ModuleType, m).__name__ if inspect.ismodule(m) else cast(str, m)
+ for m in additional_skip_names
]
self._skip_names.update(skip_names)
@@ -464,7 +576,7 @@ class Patcher:
# reload tempfile under posix to patch default argument
self.modules_to_reload: List[ModuleType] = (
- [] if sys.platform == 'win32' else [tempfile]
+ [] if sys.platform == "win32" else [tempfile]
)
if modules_to_reload is not None:
self.modules_to_reload.extend(modules_to_reload)
@@ -473,8 +585,9 @@ class Patcher:
if use_known_patches:
from pyfakefs.patched_packages import (
- get_modules_to_patch, get_classes_to_patch,
- get_fake_module_classes
+ get_modules_to_patch,
+ get_classes_to_patch,
+ get_fake_module_classes,
)
modules_to_patch = modules_to_patch or {}
@@ -516,13 +629,18 @@ class Patcher:
self._dyn_patcher: Optional[DynamicPatcher] = None
self._patching = False
- def clear_cache(self) -> None:
+ @classmethod
+ def clear_fs_cache(cls) -> None:
"""Clear the module cache."""
- self.__class__.CACHED_MODULES = set()
- self.__class__.FS_MODULES = {}
- self.__class__.FS_FUNCTIONS = {}
- self.__class__.FS_DEFARGS = []
- self.__class__.SKIPPED_FS_MODULES = {}
+ cls.CACHED_MODULES = set()
+ cls.FS_MODULES = {}
+ cls.FS_FUNCTIONS = {}
+ cls.FS_DEFARGS = []
+ cls.SKIPPED_FS_MODULES = {}
+
+ def clear_cache(self) -> None:
+ """Clear the module cache (convenience instance method)."""
+ self.__class__.clear_fs_cache()
def _init_fake_module_classes(self) -> None:
# IMPORTANT TESTING NOTE: Whenever you add a new module below, test
@@ -530,63 +648,63 @@ class Patcher:
# and a test in fake_filesystem_unittest_test.py, class
# TestAttributesWithFakeModuleNames.
self._fake_module_classes = {
- 'os': fake_filesystem.FakeOsModule,
- 'shutil': fake_filesystem_shutil.FakeShutilModule,
- 'io': fake_filesystem.FakeIoModule,
- 'pathlib': fake_pathlib.FakePathlibModule
+ "os": fake_os.FakeOsModule,
+ "shutil": fake_filesystem_shutil.FakeShutilModule,
+ "io": fake_io.FakeIoModule,
+ "pathlib": fake_pathlib.FakePathlibModule,
}
if IS_PYPY:
# in PyPy io.open, the module is referenced as _io
- self._fake_module_classes['_io'] = fake_filesystem.FakeIoModule
- if sys.platform != 'win32':
- self._fake_module_classes[
- 'fcntl'] = fake_filesystem.FakeFcntlModule
+ self._fake_module_classes["_io"] = fake_io.FakeIoModule
+ if sys.platform == "win32":
+ self._fake_module_classes["nt"] = fake_path.FakeNtModule
+ else:
+ self._fake_module_classes["fcntl"] = fake_filesystem.FakeFcntlModule
# class modules maps class names against a list of modules they can
# be contained in - this allows for alternative modules like
# `pathlib` and `pathlib2`
- self._class_modules['Path'] = ['pathlib']
- self._unfaked_module_classes[
- 'pathlib'] = fake_pathlib.RealPathlibModule
+ self._class_modules["Path"] = ["pathlib"]
+ self._unfaked_module_classes["pathlib"] = fake_pathlib.RealPathlibModule
if pathlib2:
- self._fake_module_classes[
- 'pathlib2'] = fake_pathlib.FakePathlibModule
- self._class_modules['Path'].append('pathlib2')
- self._unfaked_module_classes[
- 'pathlib2'] = fake_pathlib.RealPathlibModule
- self._fake_module_classes[
- 'Path'] = fake_pathlib.FakePathlibPathModule
- self._unfaked_module_classes[
- 'Path'] = fake_pathlib.RealPathlibPathModule
+ self._fake_module_classes["pathlib2"] = fake_pathlib.FakePathlibModule
+ self._class_modules["Path"].append("pathlib2")
+ self._unfaked_module_classes["pathlib2"] = fake_pathlib.RealPathlibModule
+ self._fake_module_classes["Path"] = fake_pathlib.FakePathlibPathModule
+ self._unfaked_module_classes["Path"] = fake_pathlib.RealPathlibPathModule
if use_scandir:
- self._fake_module_classes[
- 'scandir'] = fake_scandir.FakeScanDirModule
+ self._fake_module_classes["scandir"] = fake_scandir.FakeScanDirModule
def _init_fake_module_functions(self) -> None:
# handle patching function imported separately like
# `from os import stat`
# each patched function name has to be looked up separately
for mod_name, fake_module in self._fake_module_classes.items():
- if (hasattr(fake_module, 'dir') and
- inspect.isfunction(fake_module.dir)):
- for fct_name in fake_module.dir():
- module_attr = (getattr(fake_module, fct_name), mod_name)
- self._fake_module_functions.setdefault(
- fct_name, {})[mod_name] = module_attr
- if mod_name == 'os':
- self._fake_module_functions.setdefault(
- fct_name, {})[OS_MODULE] = module_attr
+ if hasattr(fake_module, "dir"):
+ module_dir = fake_module.dir
+ if inspect.isfunction(module_dir):
+ for fct_name in fake_module.dir():
+ module_attr = (getattr(fake_module, fct_name), mod_name)
+ self._fake_module_functions.setdefault(fct_name, {})[
+ mod_name
+ ] = module_attr
+ if mod_name == "os":
+ self._fake_module_functions.setdefault(fct_name, {})[
+ OS_MODULE
+ ] = module_attr
# special handling for functions in os.path
fake_module = fake_filesystem.FakePathModule
for fct_name in fake_module.dir():
module_attr = (getattr(fake_module, fct_name), PATH_MODULE)
- self._fake_module_functions.setdefault(
- fct_name, {})['genericpath'] = module_attr
- self._fake_module_functions.setdefault(
- fct_name, {})[PATH_MODULE] = module_attr
-
- def __enter__(self) -> 'Patcher':
+ self._fake_module_functions.setdefault(fct_name, {})[
+ "genericpath"
+ ] = module_attr
+ self._fake_module_functions.setdefault(fct_name, {})[
+ PATH_MODULE
+ ] = module_attr
+
+ def __enter__(self) -> "Patcher":
"""Context manager for usage outside of
fake_filesystem_unittest.TestCase.
Ensure that all patched modules are removed in case of an
@@ -595,49 +713,45 @@ class Patcher:
self.setUp()
return self
- def __exit__(self,
- exc_type: Optional[Type[BaseException]],
- exc_val: Optional[BaseException],
- exc_tb: Optional[TracebackType]) -> None:
+ def __exit__(
+ self,
+ exc_type: Optional[Type[BaseException]],
+ exc_val: Optional[BaseException],
+ exc_tb: Optional[TracebackType],
+ ) -> None:
self.tearDown()
- def _is_fs_module(self, mod: ModuleType,
- name: str,
- module_names: List[str]) -> bool:
- try:
- # check for __name__ first and ignore the AttributeException
- # if it does not exist - avoids calling expansive ismodule
- if mod.__name__ in module_names and inspect.ismodule(mod):
- return True
- except Exception:
- pass
+ def _is_fs_module(
+ self, mod: ModuleType, name: str, module_names: List[str]
+ ) -> bool:
try:
- if (name in self._class_modules and
- mod.__module__ in self._class_modules[name]):
- return inspect.isclass(mod)
+ return (
+ inspect.ismodule(mod)
+ and mod.__name__ in module_names
+ or inspect.isclass(mod)
+ and mod.__module__ in self._class_modules.get(name, [])
+ )
except Exception:
- # handle AttributeError and any other exception possibly triggered
- # by side effects of inspect methods
- pass
- return False
+ # handle cases where the module has no __name__ or __module__
+ # attribute - see #460, and any other exception triggered
+ # by inspect functions
+ return False
def _is_fs_function(self, fct: FunctionType) -> bool:
try:
- # check for __name__ first and ignore the AttributeException
- # if it does not exist - avoids calling expansive inspect
- # methods in most cases
- return (fct.__name__ in self._fake_module_functions and
- fct.__module__ in self._fake_module_functions[
- fct.__name__] and
- (inspect.isfunction(fct) or inspect.isbuiltin(fct)))
+ return (
+ (inspect.isfunction(fct) or inspect.isbuiltin(fct))
+ and fct.__name__ in self._fake_module_functions
+ and fct.__module__ in self._fake_module_functions[fct.__name__]
+ )
except Exception:
- # handle AttributeError and any other exception possibly triggered
- # by side effects of inspect methods
+ # handle cases where the function has no __name__ or __module__
+ # attribute, or any other exception in inspect functions
return False
def _def_values(
- self,
- item: FunctionType) -> Iterator[Tuple[FunctionType, int, Any]]:
+ self, item: FunctionType
+ ) -> Iterator[Tuple[FunctionType, int, Any]]:
"""Find default arguments that are file-system functions to be
patched in top-level functions and members of top-level classes."""
# check for module-level functions
@@ -653,8 +767,7 @@ class Patcher:
# check for methods in class
# (nested classes are ignored for now)
# inspect.getmembers is very expansive!
- for m in inspect.getmembers(item,
- predicate=inspect.isfunction):
+ for m in inspect.getmembers(item, predicate=inspect.isfunction):
f = cast(FunctionType, m[1])
if f.__defaults__:
for i, d in enumerate(f.__defaults__):
@@ -666,8 +779,7 @@ class Patcher:
# _DontDoThat() (see #523)
pass
- def _find_def_values(
- self, module_items: ItemsView[str, FunctionType]) -> None:
+ def _find_def_values(self, module_items: ItemsView[str, FunctionType]) -> None:
for _, fct in module_items:
for f, i, d in self._def_values(fct):
self.__class__.FS_DEFARGS.append((f, i, d))
@@ -680,8 +792,11 @@ class Patcher:
module_names = list(self._fake_module_classes.keys()) + [PATH_MODULE]
for name, module in list(sys.modules.items()):
try:
- if (self.use_cache and module in self.CACHED_MODULES or
- not inspect.ismodule(module)):
+ if (
+ self.use_cache
+ and module in self.CACHED_MODULES
+ or not inspect.ismodule(module)
+ ):
continue
except Exception:
# workaround for some py (part of pytest) versions
@@ -691,30 +806,35 @@ class Patcher:
if self.use_cache:
self.__class__.CACHED_MODULES.add(module)
continue
- skipped = (module in self.SKIPMODULES or
- any([sn.startswith(module.__name__)
- for sn in self._skip_names]))
+ skipped = module in self.SKIPMODULES or any(
+ [sn.startswith(module.__name__) for sn in self._skip_names]
+ )
module_items = module.__dict__.copy().items()
- modules = {name: mod for name, mod in module_items
- if self._is_fs_module(mod, name, module_names)}
+ modules = {
+ name: mod
+ for name, mod in module_items
+ if self._is_fs_module(mod, name, module_names)
+ }
if skipped:
for name, mod in modules.items():
- self.__class__.SKIPPED_FS_MODULES.setdefault(
- name, set()).add((module, mod.__name__))
+ self.__class__.SKIPPED_FS_MODULES.setdefault(name, set()).add(
+ (module, mod.__name__)
+ )
else:
for name, mod in modules.items():
self.__class__.FS_MODULES.setdefault(name, set()).add(
- (module, mod.__name__))
- functions = {name: fct for name, fct in
- module_items
- if self._is_fs_function(fct)}
+ (module, mod.__name__)
+ )
+ functions = {
+ name: fct for name, fct in module_items if self._is_fs_function(fct)
+ }
for name, fct in functions.items():
self.__class__.FS_FUNCTIONS.setdefault(
- (name, fct.__name__, fct.__module__),
- set()).add(module)
+ (name, fct.__name__, fct.__module__), set()
+ ).add(module)
# find default arguments that are file system functions
if self.patch_default_args:
@@ -729,13 +849,14 @@ class Patcher:
self._stubs.smart_unset_all()
self._stubs = mox3_stubout.StubOutForTesting()
- self.fs = fake_filesystem.FakeFilesystem(patcher=self)
+ self.fs = fake_filesystem.FakeFilesystem(patcher=self, create_temp_dir=True)
self.fs.patch_open_code = self.patch_open_code
+ self.fake_open = fake_open.FakeFileOpen(self.fs)
for name in self._fake_module_classes:
self.fake_modules[name] = self._fake_module_classes[name](self.fs)
- if hasattr(self.fake_modules[name], 'skip_names'):
+ if hasattr(self.fake_modules[name], "skip_names"):
self.fake_modules[name].skip_names = self._skip_names
- self.fake_modules[PATH_MODULE] = self.fake_modules['os'].path
+ self.fake_modules[PATH_MODULE] = self.fake_modules["os"].path
for name in self._unfaked_module_classes:
self.unfaked_modules[name] = self._unfaked_module_classes[name]()
@@ -745,18 +866,25 @@ class Patcher:
"""Bind the file-related modules to the :py:mod:`pyfakefs` fake
modules real ones. Also bind the fake `file()` and `open()` functions.
"""
- self.has_fcopy_file = (sys.platform == 'darwin' and
- hasattr(shutil, '_HAS_FCOPYFILE') and
- shutil._HAS_FCOPYFILE)
+ if self.is_doc_test:
+ self.__class__.DOC_REF_COUNT += 1
+ if self.__class__.DOC_REF_COUNT > 1:
+ return
+ else:
+ self.__class__.REF_COUNT += 1
+ if self.__class__.REF_COUNT > 1:
+ return
+ self.has_fcopy_file = (
+ sys.platform == "darwin"
+ and hasattr(shutil, "_HAS_FCOPYFILE")
+ and shutil._HAS_FCOPYFILE
+ )
if self.has_fcopy_file:
shutil._HAS_FCOPYFILE = False # type: ignore[attr-defined]
- temp_dir = tempfile.gettempdir()
with warnings.catch_warnings():
# ignore warnings, see #542 and #614
- warnings.filterwarnings(
- 'ignore'
- )
+ warnings.filterwarnings("ignore")
self._find_modules()
self._refresh()
@@ -768,11 +896,6 @@ class Patcher:
linecache.open = self.original_open # type: ignore[attr-defined]
tokenize._builtin_open = self.original_open # type: ignore
- # the temp directory is assumed to exist at least in `tempfile1`,
- # so we create it here for convenience
- assert self.fs is not None
- self.fs.create_dir(temp_dir)
-
def start_patching(self) -> None:
if not self._patching:
self._patching = True
@@ -792,7 +915,9 @@ class Patcher:
for (name, ft_name, ft_mod), modules in self.FS_FUNCTIONS.items():
method, mod_name = self._fake_module_functions[ft_name][ft_mod]
fake_module = self.fake_modules[mod_name]
- attr = method.__get__(fake_module, fake_module.__class__)
+ attr = method.__get__(
+ fake_module, fake_module.__class__
+ ) # pytype: disable=attribute-error
for module in modules:
self._stubs.smart_set(module, name, attr)
@@ -800,20 +925,22 @@ class Patcher:
assert self._stubs is not None
for name, modules in self.FS_MODULES.items():
for module, attr in modules:
- self._stubs.smart_set(
- module, name, self.fake_modules[attr])
+ self._stubs.smart_set(module, name, self.fake_modules[attr])
for name, modules in self.SKIPPED_FS_MODULES.items():
for module, attr in modules:
if attr in self.unfaked_modules:
- self._stubs.smart_set(
- module, name, self.unfaked_modules[attr])
+ self._stubs.smart_set(module, name, self.unfaked_modules[attr])
+ if sys.version_info >= (3, 12):
+ # workaround for patching open - does not work with skip modules
+ self._stubs.smart_set(builtins, "open", self.fake_open)
def patch_defaults(self) -> None:
- for (fct, idx, ft) in self.FS_DEFARGS:
- method, mod_name = self._fake_module_functions[
- ft.__name__][ft.__module__]
+ for fct, idx, ft in self.FS_DEFARGS:
+ method, mod_name = self._fake_module_functions[ft.__name__][ft.__module__]
fake_module = self.fake_modules[mod_name]
- attr = method.__get__(fake_module, fake_module.__class__)
+ attr = method.__get__(
+ fake_module, fake_module.__class__
+ ) # pytype: disable=attribute-error
new_defaults = []
assert fct.__defaults__ is not None
for i, d in enumerate(fct.__defaults__):
@@ -834,11 +961,23 @@ class Patcher:
def tearDown(self, doctester: Any = None):
"""Clear the fake filesystem bindings created by `setUp()`."""
+ if self.is_doc_test:
+ self.__class__.DOC_REF_COUNT -= 1
+ if self.__class__.DOC_REF_COUNT > 0:
+ return
+ else:
+ self.__class__.REF_COUNT -= 1
+ if self.__class__.REF_COUNT > 0:
+ return
self.stop_patching()
if self.has_fcopy_file:
shutil._HAS_FCOPYFILE = True # type: ignore[attr-defined]
reset_ids()
+ if self.is_doc_test:
+ self.__class__.DOC_PATCHER = None
+ else:
+ self.__class__.PATCHER = None
def stop_patching(self) -> None:
if self._patching:
@@ -852,7 +991,7 @@ class Patcher:
sys.meta_path.pop(0)
def unset_defaults(self) -> None:
- for (fct, idx, ft) in self.FS_DEFARGS:
+ for fct, idx, ft in self.FS_DEFARGS:
new_defaults = []
for i, d in enumerate(cast(Tuple, fct.__defaults__)):
if i == idx:
@@ -898,10 +1037,12 @@ class Pause:
elif isinstance(caller, FakeFilesystem):
self._fs = caller
else:
- raise ValueError('Invalid argument - should be of type '
- '"fake_filesystem_unittest.Patcher", '
- '"fake_filesystem_unittest.TestCase" '
- 'or "fake_filesystem.FakeFilesystem"')
+ raise ValueError(
+ "Invalid argument - should be of type "
+ '"fake_filesystem_unittest.Patcher", '
+ '"fake_filesystem_unittest.TestCase" '
+ 'or "fake_filesystem.FakeFilesystem"'
+ )
def __enter__(self) -> FakeFilesystem:
self._fs.pause()
@@ -939,8 +1080,9 @@ class DynamicPatcher(MetaPathFinder, Loader):
for module in self._patcher.modules_to_reload:
if module.__name__ in sys.modules:
reload(module)
- reloaded_module_names = [module.__name__
- for module in self._patcher.modules_to_reload]
+ reloaded_module_names = [
+ module.__name__ for module in self._patcher.modules_to_reload
+ ]
# Dereference all modules loaded during the test so they will reload on
# the next use, ensuring that no faked modules are referenced after the
# test.
@@ -953,14 +1095,16 @@ class DynamicPatcher(MetaPathFinder, Loader):
if name not in self.modules:
self._loaded_module_names.add(name)
return False
- if (name in sys.modules and
- type(sys.modules[name]) == self.modules[name]):
+ if name in sys.modules and type(sys.modules[name]) is self.modules[name]:
return False
return True
- def find_spec(self, fullname: str,
- path: Optional[Sequence[Union[bytes, str]]],
- target: Optional[ModuleType] = None) -> Optional[ModuleSpec]:
+ def find_spec(
+ self,
+ fullname: str,
+ path: Optional[Sequence[Union[bytes, str]]],
+ target: Optional[ModuleType] = None,
+ ) -> Optional[ModuleSpec]:
"""Module finder."""
if self.needs_patch(fullname):
return ModuleSpec(fullname, self)
diff --git a/pyfakefs/fake_io.py b/pyfakefs/fake_io.py
new file mode 100644
index 0000000..fc719ad
--- /dev/null
+++ b/pyfakefs/fake_io.py
@@ -0,0 +1,188 @@
+# Copyright 2009 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+""" Uses :py:class:`FakeIoModule` to provide a
+ fake ``io`` module replacement.
+"""
+import io
+import os
+import sys
+import traceback
+from enum import Enum
+from typing import (
+ List,
+ Optional,
+ Callable,
+ Union,
+ Any,
+ AnyStr,
+ IO,
+ TYPE_CHECKING,
+)
+
+from pyfakefs.fake_file import AnyFileWrapper
+from pyfakefs.fake_open import FakeFileOpen
+from pyfakefs.helpers import IS_PYPY
+
+if TYPE_CHECKING:
+ from pyfakefs.fake_filesystem import FakeFilesystem
+
+
+class PatchMode(Enum):
+ """Defines if patching shall be on, off, or in automatic mode.
+ Currently only used for `patch_open_code` option.
+ """
+
+ OFF = 1
+ AUTO = 2
+ ON = 3
+
+
+class FakeIoModule:
+ """Uses FakeFilesystem to provide a fake io module replacement.
+
+ You need a fake_filesystem to use this:
+ filesystem = fake_filesystem.FakeFilesystem()
+ my_io_module = fake_io.FakeIoModule(filesystem)
+ """
+
+ @staticmethod
+ def dir() -> List[str]:
+ """Return the list of patched function names. Used for patching
+ functions imported from the module.
+ """
+ _dir = ["open"]
+ if sys.version_info >= (3, 8):
+ _dir.append("open_code")
+ return _dir
+
+ def __init__(self, filesystem: "FakeFilesystem"):
+ """
+ Args:
+ filesystem: FakeFilesystem used to provide file system information.
+ """
+ self.filesystem = filesystem
+ self.skip_names: List[str] = []
+ self._io_module = io
+
+ def open(
+ self,
+ file: Union[AnyStr, int],
+ mode: str = "r",
+ buffering: int = -1,
+ encoding: Optional[str] = None,
+ errors: Optional[str] = None,
+ newline: Optional[str] = None,
+ closefd: bool = True,
+ opener: Optional[Callable] = None,
+ ) -> Union[AnyFileWrapper, IO[Any]]:
+ """Redirect the call to FakeFileOpen.
+ See FakeFileOpen.call() for description.
+ """
+ # workaround for built-in open called from skipped modules (see #552)
+ # as open is not imported explicitly, we cannot patch it for
+ # specific modules; instead we check if the caller is a skipped
+ # module (should work in most cases)
+ stack = traceback.extract_stack(limit=2)
+ module_name = os.path.splitext(stack[0].filename)[0]
+ module_name = module_name.replace(os.sep, ".")
+ if any(
+ [
+ module_name == sn or module_name.endswith("." + sn)
+ for sn in self.skip_names
+ ]
+ ):
+ return io.open( # pytype: disable=wrong-arg-count
+ file,
+ mode,
+ buffering,
+ encoding,
+ errors,
+ newline,
+ closefd,
+ opener,
+ )
+ fake_open = FakeFileOpen(self.filesystem)
+ return fake_open(
+ file, mode, buffering, encoding, errors, newline, closefd, opener
+ )
+
+ if sys.version_info >= (3, 8):
+
+ def open_code(self, path):
+ """Redirect the call to open. Note that the behavior of the real
+ function may be overridden by an earlier call to the
+ PyFile_SetOpenCodeHook(). This behavior is not reproduced here.
+ """
+ if not isinstance(path, str) and not IS_PYPY:
+ raise TypeError("open_code() argument 'path' must be str, not int")
+ patch_mode = self.filesystem.patch_open_code
+ if (
+ patch_mode == PatchMode.AUTO
+ and self.filesystem.exists(path)
+ or patch_mode == PatchMode.ON
+ ):
+ return self.open(path, mode="rb")
+ # mostly this is used for compiled code -
+ # don't patch these, as the files are probably in the real fs
+ return self._io_module.open_code(path)
+
+ def __getattr__(self, name):
+ """Forwards any unfaked calls to the standard io module."""
+ return getattr(self._io_module, name)
+
+
+if sys.platform != "win32":
+ import fcntl
+
+ class FakeFcntlModule:
+ """Replaces the fcntl module. Only valid under Linux/MacOS,
+ currently just mocks the functionality away.
+ """
+
+ @staticmethod
+ def dir() -> List[str]:
+ """Return the list of patched function names. Used for patching
+ functions imported from the module.
+ """
+ return ["fcntl", "ioctl", "flock", "lockf"]
+
+ def __init__(self, filesystem: "FakeFilesystem"):
+ """
+ Args:
+ filesystem: FakeFilesystem used to provide file system
+ information (currently not used).
+ """
+ self.filesystem = filesystem
+ self._fcntl_module = fcntl
+
+ def fcntl(self, fd: int, cmd: int, arg: int = 0) -> Union[int, bytes]:
+ return 0 if isinstance(arg, int) else arg
+
+ def ioctl(
+ self, fd: int, request: int, arg: int = 0, mutate_flag: bool = True
+ ) -> Union[int, bytes]:
+ return 0 if isinstance(arg, int) else arg
+
+ def flock(self, fd: int, operation: int) -> None:
+ pass
+
+ def lockf(
+ self, fd: int, cmd: int, len: int = 0, start: int = 0, whence=0
+ ) -> Any:
+ pass
+
+ def __getattr__(self, name):
+ """Forwards any unfaked calls to the standard fcntl module."""
+ return getattr(self._fcntl_module, name)
diff --git a/pyfakefs/fake_open.py b/pyfakefs/fake_open.py
new file mode 100644
index 0000000..912ada9
--- /dev/null
+++ b/pyfakefs/fake_open.py
@@ -0,0 +1,361 @@
+# Copyright 2009 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""A fake open() function replacement. See ``fake_filesystem`` for usage.
+"""
+import errno
+import os
+import sys
+from collections import namedtuple
+from stat import (
+ S_ISDIR,
+)
+from typing import (
+ Optional,
+ Union,
+ Any,
+ Tuple,
+ cast,
+ AnyStr,
+ TYPE_CHECKING,
+)
+
+from pyfakefs import helpers
+from pyfakefs.fake_file import (
+ FakePipeWrapper,
+ FakeFileWrapper,
+ FakeFile,
+ AnyFileWrapper,
+)
+from pyfakefs.helpers import (
+ AnyString,
+ is_root,
+ PERM_READ,
+ PERM_WRITE,
+)
+
+if TYPE_CHECKING:
+ from pyfakefs.fake_filesystem import FakeFilesystem
+
+
+_OpenModes = namedtuple(
+ "_OpenModes",
+ "must_exist can_read can_write truncate append must_not_exist",
+)
+
+_OPEN_MODE_MAP = {
+ # mode name:(file must exist, can read, can write,
+ # truncate, append, must not exist)
+ "r": (True, True, False, False, False, False),
+ "w": (False, False, True, True, False, False),
+ "a": (False, False, True, False, True, False),
+ "r+": (True, True, True, False, False, False),
+ "w+": (False, True, True, True, False, False),
+ "a+": (False, True, True, False, True, False),
+ "x": (False, False, True, False, False, True),
+ "x+": (False, True, True, False, False, True),
+}
+
+
+class FakeFileOpen:
+ """Faked `file()` and `open()` function replacements.
+
+ Returns FakeFile objects in a FakeFilesystem in place of the `file()`
+ or `open()` function.
+ """
+
+ __name__ = "FakeFileOpen"
+
+ def __init__(
+ self,
+ filesystem: "FakeFilesystem",
+ delete_on_close: bool = False,
+ raw_io: bool = False,
+ ):
+ """
+ Args:
+ filesystem: FakeFilesystem used to provide file system information
+ delete_on_close: optional boolean, deletes file on close()
+ """
+ self.filesystem = filesystem
+ self._delete_on_close = delete_on_close
+ self.raw_io = raw_io
+
+ def __call__(self, *args: Any, **kwargs: Any) -> AnyFileWrapper:
+ """Redirects calls to file() or open() to appropriate method."""
+ return self.call(*args, **kwargs)
+
+ def call(
+ self,
+ file_: Union[AnyStr, int],
+ mode: str = "r",
+ buffering: int = -1,
+ encoding: Optional[str] = None,
+ errors: Optional[str] = None,
+ newline: Optional[str] = None,
+ closefd: bool = True,
+ opener: Any = None,
+ open_modes: Optional[_OpenModes] = None,
+ ) -> AnyFileWrapper:
+ """Return a file-like object with the contents of the target
+ file object.
+
+ Args:
+ file_: Path to target file or a file descriptor.
+ mode: Additional file modes (all modes in `open()` are supported).
+ buffering: the buffer size used for writing. Data will only be
+ flushed if buffer size is exceeded. The default (-1) uses a
+ system specific default buffer size. Text line mode (e.g.
+ buffering=1 in text mode) is not supported.
+ encoding: The encoding used to encode unicode strings / decode
+ bytes.
+ errors: (str) Defines how encoding errors are handled.
+ newline: Controls universal newlines, passed to stream object.
+ closefd: If a file descriptor rather than file name is passed,
+ and this is set to `False`, then the file descriptor is kept
+ open when file is closed.
+ opener: an optional function object that will be called with
+ `file_` and the open flags (derived from `mode`) and returns
+ a file descriptor.
+ open_modes: Modes for opening files if called from low-level API.
+
+ Returns:
+ A file-like object containing the contents of the target file.
+
+ Raises:
+ OSError depending on Python version / call mode:
+ - if the target object is a directory
+ - on an invalid path
+ - if the file does not exist when it should
+ - if the file exists but should not
+ - if permission is denied
+ ValueError: for an invalid mode or mode combination
+ """
+ binary = "b" in mode
+
+ if binary and encoding:
+ raise ValueError("binary mode doesn't take an encoding argument")
+
+ newline, open_modes = self._handle_file_mode(mode, newline, open_modes)
+
+ # the pathlib opener is defined in a Path instance that may not be
+ # patched under some circumstances; as it just calls standard open(),
+ # we may ignore it, as it would not change the behavior
+ if opener is not None and opener.__module__ != "pathlib":
+ # opener shall return a file descriptor, which will be handled
+ # here as if directly passed
+ file_ = opener(file_, self._open_flags_from_open_modes(open_modes))
+
+ file_object, file_path, filedes, real_path = self._handle_file_arg(file_)
+ if file_object is None and file_path is None:
+ # file must be a fake pipe wrapper, find it...
+ if (
+ filedes is None
+ or len(self.filesystem.open_files) <= filedes
+ or not self.filesystem.open_files[filedes]
+ ):
+ raise OSError(errno.EBADF, "invalid pipe file descriptor")
+ wrappers = self.filesystem.open_files[filedes]
+ assert wrappers is not None
+ existing_wrapper = wrappers[0]
+ assert isinstance(existing_wrapper, FakePipeWrapper)
+ wrapper = FakePipeWrapper(
+ self.filesystem,
+ existing_wrapper.fd,
+ existing_wrapper.can_write,
+ mode,
+ )
+ file_des = self.filesystem._add_open_file(wrapper)
+ wrapper.filedes = file_des
+ return wrapper
+
+ assert file_path is not None
+ if not filedes:
+ closefd = True
+
+ if (
+ not opener
+ and open_modes.must_not_exist
+ and (
+ file_object
+ or self.filesystem.islink(file_path)
+ and not self.filesystem.is_windows_fs
+ )
+ ):
+ self.filesystem.raise_os_error(errno.EEXIST, file_path)
+
+ assert real_path is not None
+ file_object = self._init_file_object(
+ file_object, file_path, open_modes, real_path
+ )
+
+ if S_ISDIR(file_object.st_mode):
+ if self.filesystem.is_windows_fs:
+ self.filesystem.raise_os_error(errno.EACCES, file_path)
+ else:
+ self.filesystem.raise_os_error(errno.EISDIR, file_path)
+
+ # If you print obj.name, the argument to open() must be printed.
+ # Not the abspath, not the filename, but the actual argument.
+ file_object.opened_as = file_path
+ if open_modes.truncate:
+ current_time = helpers.now()
+ file_object.st_mtime = current_time
+ if not self.filesystem.is_windows_fs:
+ file_object.st_ctime = current_time
+
+ fakefile = FakeFileWrapper(
+ file_object,
+ file_path,
+ update=open_modes.can_write,
+ read=open_modes.can_read,
+ append=open_modes.append,
+ delete_on_close=self._delete_on_close,
+ filesystem=self.filesystem,
+ newline=newline,
+ binary=binary,
+ closefd=closefd,
+ encoding=encoding,
+ errors=errors,
+ buffering=buffering,
+ raw_io=self.raw_io,
+ )
+ if filedes is not None:
+ fakefile.filedes = filedes
+ # replace the file wrapper
+ open_files_list = self.filesystem.open_files[filedes]
+ assert open_files_list is not None
+ open_files_list.append(fakefile)
+ else:
+ fakefile.filedes = self.filesystem._add_open_file(fakefile)
+ return fakefile
+
+ @staticmethod
+ def _open_flags_from_open_modes(open_modes: _OpenModes) -> int:
+ flags = 0
+ if open_modes.can_read and open_modes.can_write:
+ flags |= os.O_RDWR
+ elif open_modes.can_read:
+ flags |= os.O_RDONLY
+ elif open_modes.can_write:
+ flags |= os.O_WRONLY
+
+ if open_modes.append:
+ flags |= os.O_APPEND
+ if open_modes.truncate:
+ flags |= os.O_TRUNC
+ if not open_modes.must_exist and open_modes.can_write:
+ flags |= os.O_CREAT
+ if open_modes.must_not_exist and open_modes.can_write:
+ flags |= os.O_EXCL
+ return flags
+
+ def _init_file_object(
+ self,
+ file_object: Optional[FakeFile],
+ file_path: AnyStr,
+ open_modes: _OpenModes,
+ real_path: AnyString,
+ ) -> FakeFile:
+ if file_object:
+ if not is_root() and (
+ (open_modes.can_read and not file_object.st_mode & PERM_READ)
+ or (open_modes.can_write and not file_object.st_mode & PERM_WRITE)
+ ):
+ self.filesystem.raise_os_error(errno.EACCES, file_path)
+ if open_modes.can_write:
+ if open_modes.truncate:
+ file_object.set_contents("")
+ else:
+ if open_modes.must_exist:
+ self.filesystem.raise_os_error(errno.ENOENT, file_path)
+ if self.filesystem.islink(file_path):
+ link_object = self.filesystem.resolve(file_path, follow_symlinks=False)
+ assert link_object.contents is not None
+ target_path = cast(
+ AnyStr, link_object.contents
+ ) # pytype: disable=invalid-annotation
+ else:
+ target_path = file_path
+ if self.filesystem.ends_with_path_separator(target_path):
+ error = (
+ errno.EINVAL
+ if self.filesystem.is_windows_fs
+ else errno.ENOENT
+ if self.filesystem.is_macos
+ else errno.EISDIR
+ )
+ self.filesystem.raise_os_error(error, file_path)
+ file_object = self.filesystem.create_file_internally(
+ real_path, create_missing_dirs=False, apply_umask=True
+ )
+ return file_object
+
+ def _handle_file_arg(
+ self, file_: Union[AnyStr, int]
+ ) -> Tuple[Optional[FakeFile], Optional[AnyStr], Optional[int], Optional[AnyStr]]:
+ file_object = None
+ if isinstance(file_, int):
+ # opening a file descriptor
+ filedes: int = file_
+ wrapper = self.filesystem.get_open_file(filedes)
+ if isinstance(wrapper, FakePipeWrapper):
+ return None, None, filedes, None
+ if isinstance(wrapper, FakeFileWrapper):
+ self._delete_on_close = wrapper.delete_on_close
+ file_object = cast(
+ FakeFile, self.filesystem.get_open_file(filedes).get_object()
+ )
+ assert file_object is not None
+ path = file_object.name
+ return (
+ file_object,
+ cast(AnyStr, path), # pytype: disable=invalid-annotation
+ filedes,
+ cast(AnyStr, path), # pytype: disable=invalid-annotation
+ )
+
+ # open a file file by path
+ file_path = cast(AnyStr, file_) # pytype: disable=invalid-annotation
+ if file_path == self.filesystem.dev_null.name:
+ file_object = self.filesystem.dev_null
+ real_path = file_path
+ else:
+ real_path = self.filesystem.resolve_path(file_path)
+ if self.filesystem.exists(file_path):
+ file_object = self.filesystem.get_object_from_normpath(
+ real_path, check_read_perm=False
+ )
+ return file_object, file_path, None, real_path
+
+ def _handle_file_mode(
+ self,
+ mode: str,
+ newline: Optional[str],
+ open_modes: Optional[_OpenModes],
+ ) -> Tuple[Optional[str], _OpenModes]:
+ orig_modes = mode # Save original modes for error messages.
+ # Normalize modes. Handle 't' and 'U'.
+ if ("b" in mode and "t" in mode) or (
+ sys.version_info > (3, 10) and "U" in mode
+ ):
+ raise ValueError("Invalid mode: " + mode)
+ mode = mode.replace("t", "").replace("b", "")
+ mode = mode.replace("rU", "r").replace("U", "r")
+ if not self.raw_io:
+ if mode not in _OPEN_MODE_MAP:
+ raise ValueError("Invalid mode: %r" % orig_modes)
+ open_modes = _OpenModes(*_OPEN_MODE_MAP[mode])
+ assert open_modes is not None
+ return newline, open_modes
diff --git a/pyfakefs/fake_os.py b/pyfakefs/fake_os.py
new file mode 100644
index 0000000..ba19bf8
--- /dev/null
+++ b/pyfakefs/fake_os.py
@@ -0,0 +1,1374 @@
+# Copyright 2009 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+""" Uses :py:class:`FakeOsModule` to provide a
+ fake :py:mod:`os` module replacement.
+"""
+import errno
+import functools
+import inspect
+import os
+import sys
+import uuid
+from contextlib import contextmanager
+from stat import (
+ S_IFREG,
+ S_IFSOCK,
+)
+from typing import (
+ List,
+ Optional,
+ Callable,
+ Union,
+ Any,
+ Tuple,
+ cast,
+ AnyStr,
+ TYPE_CHECKING,
+ Set,
+)
+
+from pyfakefs.extra_packages import use_scandir
+from pyfakefs.fake_file import (
+ FakeDirectory,
+ FakeDirWrapper,
+ StandardStreamWrapper,
+ FakeFileWrapper,
+ FakePipeWrapper,
+ FakeFile,
+ AnyFileWrapper,
+)
+from pyfakefs.fake_open import FakeFileOpen, _OpenModes
+from pyfakefs.fake_path import FakePathModule
+from pyfakefs.fake_scandir import scandir, walk, ScanDirIter
+from pyfakefs.helpers import (
+ FakeStatResult,
+ is_int_type,
+ is_byte_string,
+ make_string_path,
+ IS_PYPY,
+ to_string,
+ matching_string,
+ AnyString,
+ to_bytes,
+ PERM_EXE,
+ PERM_DEF,
+ is_root,
+ get_uid,
+ get_gid,
+)
+
+if TYPE_CHECKING:
+ from pyfakefs.fake_filesystem import FakeFilesystem
+
+NR_STD_STREAMS = 3
+
+
+class FakeOsModule:
+ """Uses FakeFilesystem to provide a fake os module replacement.
+
+ Do not create os.path separately from os, as there is a necessary circular
+ dependency between os and os.path to replicate the behavior of the standard
+ Python modules. What you want to do is to just let FakeOsModule take care
+ of `os.path` setup itself.
+
+ # You always want to do this.
+ filesystem = fake_filesystem.FakeFilesystem()
+ my_os_module = fake_os.FakeOsModule(filesystem)
+ """
+
+ use_original = False
+
+ @staticmethod
+ def dir() -> List[str]:
+ """Return the list of patched function names. Used for patching
+ functions imported from the module.
+ """
+ _dir = [
+ "access",
+ "chdir",
+ "chmod",
+ "chown",
+ "close",
+ "fstat",
+ "fsync",
+ "getcwd",
+ "lchmod",
+ "link",
+ "listdir",
+ "lstat",
+ "makedirs",
+ "mkdir",
+ "mknod",
+ "open",
+ "read",
+ "readlink",
+ "remove",
+ "removedirs",
+ "rename",
+ "rmdir",
+ "stat",
+ "symlink",
+ "umask",
+ "unlink",
+ "utime",
+ "walk",
+ "write",
+ "getcwdb",
+ "replace",
+ ]
+ if sys.platform.startswith("linux"):
+ _dir += [
+ "fdatasync",
+ "getxattr",
+ "listxattr",
+ "removexattr",
+ "setxattr",
+ ]
+ if sys.platform != "win32":
+ _dir += [
+ "getgid",
+ "getuid",
+ ]
+ if use_scandir:
+ _dir += ["scandir"]
+ return _dir
+
+ def __init__(self, filesystem: "FakeFilesystem"):
+ """Also exposes self.path (to fake os.path).
+
+ Args:
+ filesystem: FakeFilesystem used to provide file system information
+ """
+ self.filesystem = filesystem
+ self.os_module: Any = os
+ self.path = FakePathModule(self.filesystem, self)
+ self._supports_follow_symlinks: Optional[Set] = None
+ self._supports_dir_fd: Optional[Set] = None
+ self._supports_effective_ids: Optional[Set] = None
+ self._supports_fd: Optional[Set] = None
+
+ @property
+ def devnull(self) -> str:
+ return self.path.devnull
+
+ @property
+ def sep(self) -> str:
+ return self.path.sep
+
+ @property
+ def altsep(self) -> Optional[str]:
+ return self.path.altsep
+
+ @property
+ def linesep(self) -> str:
+ return self.path.linesep
+
+ @property
+ def pathsep(self) -> str:
+ return self.path.pathsep
+
+ def fdopen(self, fd: int, *args: Any, **kwargs: Any) -> AnyFileWrapper:
+ """Redirector to open() builtin function.
+
+ Args:
+ fd: The file descriptor of the file to open.
+ *args: Pass through args.
+ **kwargs: Pass through kwargs.
+
+ Returns:
+ File object corresponding to file_des.
+
+ Raises:
+ TypeError: if file descriptor is not an integer.
+ """
+ if not is_int_type(fd):
+ raise TypeError("an integer is required")
+ return FakeFileOpen(self.filesystem)(fd, *args, **kwargs)
+
+ def _umask(self) -> int:
+ """Return the current umask."""
+ if self.filesystem.is_windows_fs:
+ # windows always returns 0 - it has no real notion of umask
+ return 0
+ if sys.platform == "win32":
+ # if we are testing Unix under Windows we assume a default mask
+ return 0o002
+ else:
+ # under Unix, we return the real umask;
+ # as there is no pure getter for umask, so we have to first
+ # set a mode to get the previous one and then re-set that
+ mask = os.umask(0)
+ os.umask(mask)
+ return mask
+
+ def open(
+ self,
+ path: AnyStr,
+ flags: int,
+ mode: Optional[int] = None,
+ *,
+ dir_fd: Optional[int] = None
+ ) -> int:
+ """Return the file descriptor for a FakeFile.
+
+ Args:
+ path: the path to the file
+ flags: low-level bits to indicate io operation
+ mode: bits to define default permissions
+ Note: only basic modes are supported, OS-specific modes are
+ ignored
+ dir_fd: If not `None`, the file descriptor of a directory,
+ with `file_path` being relative to this directory.
+
+ Returns:
+ A file descriptor.
+
+ Raises:
+ OSError: if the path cannot be found
+ ValueError: if invalid mode is given
+ NotImplementedError: if `os.O_EXCL` is used without `os.O_CREAT`
+ """
+ path = self._path_with_dir_fd(path, self.open, dir_fd)
+ if mode is None:
+ if self.filesystem.is_windows_fs:
+ mode = 0o666
+ else:
+ mode = 0o777 & ~self._umask()
+
+ has_tmpfile_flag = (
+ hasattr(os, "O_TMPFILE") and flags & os.O_TMPFILE == os.O_TMPFILE
+ )
+ open_modes = _OpenModes(
+ must_exist=not flags & os.O_CREAT and not has_tmpfile_flag,
+ can_read=not flags & os.O_WRONLY,
+ can_write=flags & (os.O_RDWR | os.O_WRONLY) != 0,
+ truncate=flags & os.O_TRUNC != 0,
+ append=flags & os.O_APPEND != 0,
+ must_not_exist=flags & os.O_EXCL != 0,
+ )
+ if open_modes.must_not_exist and open_modes.must_exist:
+ raise NotImplementedError("O_EXCL without O_CREAT mode is not supported")
+ if has_tmpfile_flag:
+ # this is a workaround for tempfiles that do not have a filename
+ # as we do not support this directly, we just add a unique filename
+ # and set the file to delete on close
+ path = self.filesystem.joinpaths(
+ path, matching_string(path, str(uuid.uuid4()))
+ )
+
+ if not self.filesystem.is_windows_fs and self.filesystem.exists(path):
+ # handle opening directory - only allowed under Posix
+ # with read-only mode
+ obj = self.filesystem.resolve(path)
+ if isinstance(obj, FakeDirectory):
+ if (
+ not open_modes.must_exist and not self.filesystem.is_macos
+ ) or open_modes.can_write:
+ self.filesystem.raise_os_error(errno.EISDIR, path)
+ dir_wrapper = FakeDirWrapper(obj, path, self.filesystem)
+ file_des = self.filesystem._add_open_file(dir_wrapper)
+ dir_wrapper.filedes = file_des
+ return file_des
+
+ # low level open is always binary
+ str_flags = "b"
+ delete_on_close = has_tmpfile_flag
+ if hasattr(os, "O_TEMPORARY"):
+ delete_on_close = flags & os.O_TEMPORARY == os.O_TEMPORARY
+ fake_file = FakeFileOpen(
+ self.filesystem, delete_on_close=delete_on_close, raw_io=True
+ )(path, str_flags, open_modes=open_modes)
+ assert not isinstance(fake_file, StandardStreamWrapper)
+ if fake_file.file_object != self.filesystem.dev_null:
+ self.chmod(path, mode)
+ return fake_file.fileno()
+
+ def close(self, fd: int) -> None:
+ """Close a file descriptor.
+
+ Args:
+ fd: An integer file descriptor for the file object requested.
+
+ Raises:
+ OSError: bad file descriptor.
+ TypeError: if file descriptor is not an integer.
+ """
+ file_handle = self.filesystem.get_open_file(fd)
+ file_handle.close()
+
+ def read(self, fd: int, n: int) -> bytes:
+ """Read number of bytes from a file descriptor, returns bytes read.
+
+ Args:
+ fd: An integer file descriptor for the file object requested.
+ n: Number of bytes to read from file.
+
+ Returns:
+ Bytes read from file.
+
+ Raises:
+ OSError: bad file descriptor.
+ TypeError: if file descriptor is not an integer.
+ """
+ file_handle = self.filesystem.get_open_file(fd)
+ if isinstance(file_handle, FakeFileWrapper):
+ file_handle.raw_io = True
+ if isinstance(file_handle, FakeDirWrapper):
+ self.filesystem.raise_os_error(errno.EBADF, file_handle.file_path)
+ return file_handle.read(n)
+
+ def write(self, fd: int, contents: bytes) -> int:
+ """Write string to file descriptor, returns number of bytes written.
+
+ Args:
+ fd: An integer file descriptor for the file object requested.
+ contents: String of bytes to write to file.
+
+ Returns:
+ Number of bytes written.
+
+ Raises:
+ OSError: bad file descriptor.
+ TypeError: if file descriptor is not an integer.
+ """
+ file_handle = cast(FakeFileWrapper, self.filesystem.get_open_file(fd))
+ if isinstance(file_handle, FakeDirWrapper):
+ self.filesystem.raise_os_error(errno.EBADF, file_handle.file_path)
+
+ if isinstance(file_handle, FakePipeWrapper):
+ return file_handle.write(contents)
+
+ file_handle.raw_io = True
+ file_handle._sync_io()
+ file_handle.update_flush_pos()
+ file_handle.write(contents)
+ file_handle.flush()
+ return len(contents)
+
+ def pipe(self) -> Tuple[int, int]:
+ read_fd, write_fd = os.pipe()
+ read_wrapper = FakePipeWrapper(self.filesystem, read_fd, False)
+ file_des = self.filesystem._add_open_file(read_wrapper)
+ read_wrapper.filedes = file_des
+ write_wrapper = FakePipeWrapper(self.filesystem, write_fd, True)
+ file_des = self.filesystem._add_open_file(write_wrapper)
+ write_wrapper.filedes = file_des
+ return read_wrapper.filedes, write_wrapper.filedes
+
+ def fstat(self, fd: int) -> FakeStatResult:
+ """Return the os.stat-like tuple for the FakeFile object of file_des.
+
+ Args:
+ fd: The file descriptor of filesystem object to retrieve.
+
+ Returns:
+ The FakeStatResult object corresponding to entry_path.
+
+ Raises:
+ OSError: if the filesystem object doesn't exist.
+ """
+ # stat should return the tuple representing return value of os.stat
+ file_object = self.filesystem.get_open_file(fd).get_object()
+ assert isinstance(file_object, FakeFile)
+ return file_object.stat_result.copy()
+
+ def umask(self, mask: int) -> int:
+ """Change the current umask.
+
+ Args:
+ mask: (int) The new umask value.
+
+ Returns:
+ The old umask.
+
+ Raises:
+ TypeError: if new_mask is of an invalid type.
+ """
+ if not is_int_type(mask):
+ raise TypeError("an integer is required")
+ old_umask = self.filesystem.umask
+ self.filesystem.umask = mask
+ return old_umask
+
+ def chdir(self, path: AnyStr) -> None:
+ """Change current working directory to target directory.
+
+ Args:
+ path: The path to new current working directory.
+
+ Raises:
+ OSError: if user lacks permission to enter the argument directory
+ or if the target is not a directory.
+ """
+ try:
+ path = self.filesystem.resolve_path(path, allow_fd=True)
+ except OSError as exc:
+ if self.filesystem.is_macos and exc.errno == errno.EBADF:
+ raise OSError(errno.ENOTDIR, "Not a directory: " + str(path))
+ raise
+ self.filesystem.confirmdir(path)
+ directory = self.filesystem.resolve(path)
+ # A full implementation would check permissions all the way
+ # up the tree.
+ if not is_root() and not directory.st_mode | PERM_EXE:
+ self.filesystem.raise_os_error(errno.EACCES, directory.name)
+ self.filesystem.cwd = path # type: ignore[assignment]
+
+ def getcwd(self) -> str:
+ """Return current working directory."""
+ return to_string(self.filesystem.cwd)
+
+ def getcwdb(self) -> bytes:
+ """Return current working directory as bytes."""
+ return to_bytes(self.filesystem.cwd)
+
+ def listdir(self, path: AnyStr) -> List[AnyStr]:
+ """Return a list of file names in target_directory.
+
+ Args:
+ path: Path to the target directory within the fake
+ filesystem.
+
+ Returns:
+ A list of file names within the target directory in arbitrary
+ order.
+
+ Raises:
+ OSError: if the target is not a directory.
+ """
+ return self.filesystem.listdir(path)
+
+ XATTR_CREATE = 1
+ XATTR_REPLACE = 2
+
+ def getxattr(
+ self, path: AnyStr, attribute: AnyString, *, follow_symlinks: bool = True
+ ) -> Optional[bytes]:
+ """Return the value of the given extended filesystem attribute for
+ `path`.
+
+ Args:
+ path: File path, file descriptor or path-like object (for
+ Python >= 3.6).
+ attribute: (str or bytes) The attribute name.
+ follow_symlinks: (bool) If True (the default), symlinks in the
+ path are traversed.
+
+ Returns:
+ The contents of the extended attribute as bytes or None if
+ the attribute does not exist.
+
+ Raises:
+ OSError: if the path does not exist.
+ """
+ if not self.filesystem.is_linux:
+ raise AttributeError("module 'os' has no attribute 'getxattr'")
+
+ if isinstance(attribute, bytes):
+ attribute = attribute.decode(sys.getfilesystemencoding())
+ file_obj = self.filesystem.resolve(path, follow_symlinks, allow_fd=True)
+ return file_obj.xattr.get(attribute)
+
+ def listxattr(
+ self, path: Optional[AnyStr] = None, *, follow_symlinks: bool = True
+ ) -> List[str]:
+ """Return a list of the extended filesystem attributes on `path`.
+
+ Args:
+ path: File path, file descriptor or path-like object (for
+ Python >= 3.6). If None, the current directory is used.
+ follow_symlinks: (bool) If True (the default), symlinks in the
+ path are traversed.
+
+ Returns:
+ A list of all attribute names for the given path as str.
+
+ Raises:
+ OSError: if the path does not exist.
+ """
+ if not self.filesystem.is_linux:
+ raise AttributeError("module 'os' has no attribute 'listxattr'")
+
+ path_str = self.filesystem.cwd if path is None else path
+ file_obj = self.filesystem.resolve(
+ cast(AnyStr, path_str), # pytype: disable=invalid-annotation
+ follow_symlinks,
+ allow_fd=True,
+ )
+ return list(file_obj.xattr.keys())
+
+ def removexattr(
+ self, path: AnyStr, attribute: AnyString, *, follow_symlinks: bool = True
+ ) -> None:
+ """Removes the extended filesystem attribute attribute from `path`.
+
+ Args:
+ path: File path, file descriptor or path-like object (for
+ Python >= 3.6).
+ attribute: (str or bytes) The attribute name.
+ follow_symlinks: (bool) If True (the default), symlinks in the
+ path are traversed.
+
+ Raises:
+ OSError: if the path does not exist.
+ """
+ if not self.filesystem.is_linux:
+ raise AttributeError("module 'os' has no attribute 'removexattr'")
+
+ if isinstance(attribute, bytes):
+ attribute = attribute.decode(sys.getfilesystemencoding())
+ file_obj = self.filesystem.resolve(path, follow_symlinks, allow_fd=True)
+ if attribute in file_obj.xattr:
+ del file_obj.xattr[attribute]
+
+ def setxattr(
+ self,
+ path: AnyStr,
+ attribute: AnyString,
+ value: bytes,
+ flags: int = 0,
+ *,
+ follow_symlinks: bool = True
+ ) -> None:
+ """Sets the value of the given extended filesystem attribute for
+ `path`.
+
+ Args:
+ path: File path, file descriptor or path-like object (for
+ Python >= 3.6).
+ attribute: The attribute name (str or bytes).
+ value: (byte-like) The value to be set.
+ follow_symlinks: (bool) If True (the default), symlinks in the
+ path are traversed.
+
+ Raises:
+ OSError: if the path does not exist.
+ TypeError: if `value` is not a byte-like object.
+ """
+ if not self.filesystem.is_linux:
+ raise AttributeError("module 'os' has no attribute 'setxattr'")
+
+ if isinstance(attribute, bytes):
+ attribute = attribute.decode(sys.getfilesystemencoding())
+ if not is_byte_string(value):
+ raise TypeError("a bytes-like object is required")
+ file_obj = self.filesystem.resolve(path, follow_symlinks, allow_fd=True)
+ exists = attribute in file_obj.xattr
+ if exists and flags == self.XATTR_CREATE:
+ self.filesystem.raise_os_error(errno.ENODATA, file_obj.path)
+ if not exists and flags == self.XATTR_REPLACE:
+ self.filesystem.raise_os_error(errno.EEXIST, file_obj.path)
+ file_obj.xattr[attribute] = value
+
+ def scandir(self, path: str = ".") -> ScanDirIter:
+ """Return an iterator of DirEntry objects corresponding to the
+ entries in the directory given by path.
+
+ Args:
+ path: Path to the target directory within the fake filesystem.
+
+ Returns:
+ An iterator to an unsorted list of os.DirEntry objects for
+ each entry in path.
+
+ Raises:
+ OSError: if the target is not a directory.
+ """
+ return scandir(self.filesystem, path)
+
+ def walk(
+ self,
+ top: AnyStr,
+ topdown: bool = True,
+ onerror: Optional[bool] = None,
+ followlinks: bool = False,
+ ):
+ """Perform an os.walk operation over the fake filesystem.
+
+ Args:
+ top: The root directory from which to begin walk.
+ topdown: Determines whether to return the tuples with the root as
+ the first entry (`True`) or as the last, after all the child
+ directory tuples (`False`).
+ onerror: If not `None`, function which will be called to handle the
+ `os.error` instance provided when `os.listdir()` fails.
+ followlinks: If `True`, symbolic links are followed.
+
+ Yields:
+ (path, directories, nondirectories) for top and each of its
+ subdirectories. See the documentation for the builtin os module
+ for further details.
+ """
+ return walk(self.filesystem, top, topdown, onerror, followlinks)
+
+ def readlink(self, path: AnyStr, dir_fd: Optional[int] = None) -> str:
+ """Read the target of a symlink.
+
+ Args:
+ path: Symlink to read the target of.
+ dir_fd: If not `None`, the file descriptor of a directory,
+ with `path` being relative to this directory.
+
+ Returns:
+ the string representing the path to which the symbolic link points.
+
+ Raises:
+ TypeError: if `path` is None
+ OSError: (with errno=ENOENT) if path is not a valid path, or
+ (with errno=EINVAL) if path is valid, but is not a symlink
+ """
+ path = self._path_with_dir_fd(path, self.readlink, dir_fd)
+ return self.filesystem.readlink(path)
+
+ def stat(
+ self,
+ path: AnyStr,
+ *,
+ dir_fd: Optional[int] = None,
+ follow_symlinks: bool = True
+ ) -> FakeStatResult:
+ """Return the os.stat-like tuple for the FakeFile object of entry_path.
+
+ Args:
+ path: path to filesystem object to retrieve.
+ dir_fd: (int) If not `None`, the file descriptor of a directory,
+ with `entry_path` being relative to this directory.
+ follow_symlinks: (bool) If `False` and `entry_path` points to a
+ symlink, the link itself is changed instead of the linked
+ object.
+
+ Returns:
+ The FakeStatResult object corresponding to entry_path.
+
+ Raises:
+ OSError: if the filesystem object doesn't exist.
+ """
+ path = self._path_with_dir_fd(path, self.stat, dir_fd)
+ return self.filesystem.stat(path, follow_symlinks)
+
+ def lstat(self, path: AnyStr, *, dir_fd: Optional[int] = None) -> FakeStatResult:
+ """Return the os.stat-like tuple for entry_path,
+ not following symlinks.
+
+ Args:
+ path: path to filesystem object to retrieve.
+ dir_fd: If not `None`, the file descriptor of a directory, with
+ `path` being relative to this directory.
+
+ Returns:
+ the FakeStatResult object corresponding to `path`.
+
+ Raises:
+ OSError: if the filesystem object doesn't exist.
+ """
+ # stat should return the tuple representing return value of os.stat
+ path = self._path_with_dir_fd(path, self.lstat, dir_fd)
+ return self.filesystem.stat(path, follow_symlinks=False)
+
+ def remove(self, path: AnyStr, dir_fd: Optional[int] = None) -> None:
+ """Remove the FakeFile object at the specified file path.
+
+ Args:
+ path: Path to file to be removed.
+ dir_fd: If not `None`, the file descriptor of a directory,
+ with `path` being relative to this directory.
+
+ Raises:
+ OSError: if path points to a directory.
+ OSError: if path does not exist.
+ OSError: if removal failed.
+ """
+ path = self._path_with_dir_fd(path, self.remove, dir_fd)
+ self.filesystem.remove(path)
+
+ def unlink(self, path: AnyStr, *, dir_fd: Optional[int] = None) -> None:
+ """Remove the FakeFile object at the specified file path.
+
+ Args:
+ path: Path to file to be removed.
+ dir_fd: If not `None`, the file descriptor of a directory,
+ with `path` being relative to this directory.
+
+ Raises:
+ OSError: if path points to a directory.
+ OSError: if path does not exist.
+ OSError: if removal failed.
+ """
+ path = self._path_with_dir_fd(path, self.unlink, dir_fd)
+ self.filesystem.remove(path)
+
+ def rename(
+ self,
+ src: AnyStr,
+ dst: AnyStr,
+ *,
+ src_dir_fd: Optional[int] = None,
+ dst_dir_fd: Optional[int] = None
+ ) -> None:
+ """Rename a FakeFile object at old_file_path to new_file_path,
+ preserving all properties.
+ Also replaces existing new_file_path object, if one existed
+ (Unix only).
+
+ Args:
+ src: Path to filesystem object to rename.
+ dst: Path to where the filesystem object will live
+ after this call.
+ src_dir_fd: If not `None`, the file descriptor of a directory,
+ with `src` being relative to this directory.
+ dst_dir_fd: If not `None`, the file descriptor of a directory,
+ with `dst` being relative to this directory.
+
+ Raises:
+ OSError: if old_file_path does not exist.
+ OSError: if new_file_path is an existing directory.
+ OSError: if new_file_path is an existing file (Windows only)
+ OSError: if new_file_path is an existing file and could not
+ be removed (Unix)
+ OSError: if `dirname(new_file)` does not exist
+ OSError: if the file would be moved to another filesystem
+ (e.g. mount point)
+ """
+ src = self._path_with_dir_fd(src, self.rename, src_dir_fd)
+ dst = self._path_with_dir_fd(dst, self.rename, dst_dir_fd)
+ self.filesystem.rename(src, dst)
+
+ def renames(self, old: AnyStr, new: AnyStr):
+ """Fakes `os.renames`, documentation taken from there.
+
+ Super-rename; create directories as necessary and delete any left
+ empty. Works like rename, except creation of any intermediate
+ directories needed to make the new pathname good is attempted
+ first. After the rename, directories corresponding to rightmost
+ path segments of the old name will be pruned until either the
+ whole path is consumed or a nonempty directory is found.
+
+ Note: this function can fail with the new directory structure made
+ if you lack permissions needed to unlink the leaf directory or
+ file.
+
+ """
+ head, tail = self.filesystem.splitpath(new)
+ if head and tail and not self.filesystem.exists(head):
+ self.makedirs(head)
+ self.rename(old, new)
+ head, tail = self.filesystem.splitpath(old)
+ if head and tail:
+ try:
+ self.removedirs(head)
+ except OSError:
+ pass
+
+ def replace(
+ self,
+ src: AnyStr,
+ dst: AnyStr,
+ *,
+ src_dir_fd: Optional[int] = None,
+ dst_dir_fd: Optional[int] = None
+ ) -> None:
+ """Renames a FakeFile object at old_file_path to new_file_path,
+ preserving all properties.
+ Also replaces existing new_file_path object, if one existed.
+
+ Arg
+ src: Path to filesystem object to rename.
+ dst: Path to where the filesystem object will live
+ after this call.
+ src_dir_fd: If not `None`, the file descriptor of a directory,
+ with `src` being relative to this directory.
+ dst_dir_fd: If not `None`, the file descriptor of a directory,
+ with `dst` being relative to this directory.
+
+ Raises:
+ OSError: if old_file_path does not exist.
+ OSError: if new_file_path is an existing directory.
+ OSError: if new_file_path is an existing file and could
+ not be removed
+ OSError: if `dirname(new_file)` does not exist
+ OSError: if the file would be moved to another filesystem
+ (e.g. mount point)
+ """
+ src = self._path_with_dir_fd(src, self.rename, src_dir_fd)
+ dst = self._path_with_dir_fd(dst, self.rename, dst_dir_fd)
+ self.filesystem.rename(src, dst, force_replace=True)
+
+ def rmdir(self, path: AnyStr, *, dir_fd: Optional[int] = None) -> None:
+ """Remove a leaf Fake directory.
+
+ Args:
+ path: (str) Name of directory to remove.
+ dir_fd: If not `None`, the file descriptor of a directory,
+ with `path` being relative to this directory.
+
+ Raises:
+ OSError: if `path` does not exist or is not a directory,
+ or as per FakeFilesystem.remove_object. Cannot remove '.'.
+ """
+ path = self._path_with_dir_fd(path, self.rmdir, dir_fd)
+ self.filesystem.rmdir(path)
+
+ def removedirs(self, name: AnyStr) -> None:
+ """Remove a leaf fake directory and all empty intermediate ones.
+
+ Args:
+ name: the directory to be removed.
+
+ Raises:
+ OSError: if target_directory does not exist or is not a directory.
+ OSError: if target_directory is not empty.
+ """
+ name = self.filesystem.absnormpath(name)
+ directory = self.filesystem.confirmdir(name)
+ if directory.entries:
+ self.filesystem.raise_os_error(errno.ENOTEMPTY, self.path.basename(name))
+ else:
+ self.rmdir(name)
+ head, tail = self.path.split(name)
+ if not tail:
+ head, tail = self.path.split(head)
+ while head and tail:
+ head_dir = self.filesystem.confirmdir(head)
+ if head_dir.entries:
+ break
+ # only the top-level dir may not be a symlink
+ self.filesystem.rmdir(head, allow_symlink=True)
+ head, tail = self.path.split(head)
+
+ def mkdir(
+ self, path: AnyStr, mode: int = PERM_DEF, *, dir_fd: Optional[int] = None
+ ) -> None:
+ """Create a leaf Fake directory.
+
+ Args:
+ path: (str) Name of directory to create.
+ Relative paths are assumed to be relative to '/'.
+ mode: (int) Mode to create directory with. This argument defaults
+ to 0o777. The umask is applied to this mode.
+ dir_fd: If not `None`, the file descriptor of a directory,
+ with `path` being relative to this directory.
+
+ Raises:
+ OSError: if the directory name is invalid or parent directory is
+ read only or as per FakeFilesystem.add_object.
+ """
+ path = self._path_with_dir_fd(path, self.mkdir, dir_fd)
+ try:
+ self.filesystem.makedir(path, mode)
+ except OSError as e:
+ if e.errno == errno.EACCES:
+ self.filesystem.raise_os_error(e.errno, path)
+ raise
+
+ def makedirs(
+ self, name: AnyStr, mode: int = PERM_DEF, exist_ok: Optional[bool] = None
+ ) -> None:
+ """Create a leaf Fake directory + create any non-existent parent dirs.
+
+ Args:
+ name: (str) Name of directory to create.
+ mode: (int) Mode to create directory (and any necessary parent
+ directories) with. This argument defaults to 0o777.
+ The umask is applied to this mode.
+ exist_ok: (boolean) If exist_ok is False (the default), an OSError
+ is raised if the target directory already exists.
+
+ Raises:
+ OSError: if the directory already exists and exist_ok=False, or as
+ per :py:meth:`FakeFilesystem.create_dir`.
+ """
+ if exist_ok is None:
+ exist_ok = False
+ self.filesystem.makedirs(name, mode, exist_ok)
+
+ def _path_with_dir_fd(
+ self, path: AnyStr, fct: Callable, dir_fd: Optional[int]
+ ) -> AnyStr:
+ """Return the path considering dir_fd. Raise on invalid parameters."""
+ try:
+ path = make_string_path(path)
+ except TypeError:
+ # the error is handled later
+ path = path
+ if dir_fd is not None:
+ # check if fd is supported for the built-in real function
+ if fct not in self.supports_dir_fd:
+ raise NotImplementedError("dir_fd unavailable on this platform")
+ if isinstance(path, int):
+ raise ValueError(
+ "%s: Can't specify dir_fd without "
+ "matching path_str" % fct.__name__
+ )
+ if not self.path.isabs(path):
+ open_file = self.filesystem.get_open_file(dir_fd)
+ return self.path.join( # type: ignore[type-var, return-value]
+ cast(FakeFile, open_file.get_object()).path, path
+ )
+ return path
+
+ def truncate(self, path: AnyStr, length: int) -> None:
+ """Truncate the file corresponding to path, so that it is
+ length bytes in size. If length is larger than the current size,
+ the file is filled up with zero bytes.
+
+ Args:
+ path: (str or int) Path to the file, or an integer file
+ descriptor for the file object.
+ length: (int) Length of the file after truncating it.
+
+ Raises:
+ OSError: if the file does not exist or the file descriptor is
+ invalid.
+ """
+ file_object = self.filesystem.resolve(path, allow_fd=True)
+ file_object.size = length
+
+ def ftruncate(self, fd: int, length: int) -> None:
+ """Truncate the file corresponding to fd, so that it is
+ length bytes in size. If length is larger than the current size,
+ the file is filled up with zero bytes.
+
+ Args:
+ fd: (int) File descriptor for the file object.
+ length: (int) Maximum length of the file after truncating it.
+
+ Raises:
+ OSError: if the file descriptor is invalid
+ """
+ file_object = self.filesystem.get_open_file(fd).get_object()
+ if isinstance(file_object, FakeFileWrapper):
+ file_object.size = length
+ else:
+ raise OSError(errno.EBADF, "Invalid file descriptor")
+
+ def access(
+ self,
+ path: AnyStr,
+ mode: int,
+ *,
+ dir_fd: Optional[int] = None,
+ effective_ids: bool = False,
+ follow_symlinks: bool = True
+ ) -> bool:
+ """Check if a file exists and has the specified permissions.
+
+ Args:
+ path: (str) Path to the file.
+ mode: (int) Permissions represented as a bitwise-OR combination of
+ os.F_OK, os.R_OK, os.W_OK, and os.X_OK.
+ dir_fd: If not `None`, the file descriptor of a directory, with
+ `path` being relative to this directory.
+ effective_ids: (bool) Unused. Only here to match the signature.
+ follow_symlinks: (bool) If `False` and `path` points to a symlink,
+ the link itself is queried instead of the linked object.
+
+ Returns:
+ bool, `True` if file is accessible, `False` otherwise.
+ """
+ if effective_ids and self.filesystem.is_windows_fs:
+ raise NotImplementedError(
+ "access: effective_ids unavailable on this platform"
+ )
+ path = self._path_with_dir_fd(path, self.access, dir_fd)
+ try:
+ stat_result = self.stat(path, follow_symlinks=follow_symlinks)
+ except OSError as os_error:
+ if os_error.errno == errno.ENOENT:
+ return False
+ raise
+ if is_root():
+ mode &= ~os.W_OK
+ return (mode & ((stat_result.st_mode >> 6) & 7)) == mode
+
+ def chmod(
+ self,
+ path: AnyStr,
+ mode: int,
+ *,
+ dir_fd: Optional[int] = None,
+ follow_symlinks: bool = True
+ ) -> None:
+ """Change the permissions of a file as encoded in integer mode.
+
+ Args:
+ path: (str) Path to the file.
+ mode: (int) Permissions.
+ dir_fd: If not `None`, the file descriptor of a directory, with
+ `path` being relative to this directory.
+ follow_symlinks: (bool) If `False` and `path` points to a symlink,
+ the link itself is queried instead of the linked object.
+ """
+ if not follow_symlinks and (
+ self.chmod not in self.supports_follow_symlinks or IS_PYPY
+ ):
+ raise NotImplementedError(
+ "`follow_symlinks` for chmod() is not available " "on this system"
+ )
+ path = self._path_with_dir_fd(path, self.chmod, dir_fd)
+ self.filesystem.chmod(path, mode, follow_symlinks)
+
+ def lchmod(self, path: AnyStr, mode: int) -> None:
+ """Change the permissions of a file as encoded in integer mode.
+ If the file is a link, the permissions of the link are changed.
+
+ Args:
+ path: (str) Path to the file.
+ mode: (int) Permissions.
+ """
+ if self.filesystem.is_windows_fs:
+ raise NameError("name 'lchmod' is not defined")
+ self.filesystem.chmod(path, mode, follow_symlinks=False)
+
+ def utime(
+ self,
+ path: AnyStr,
+ times: Optional[Tuple[Union[int, float], Union[int, float]]] = None,
+ ns: Optional[Tuple[int, int]] = None,
+ dir_fd: Optional[int] = None,
+ follow_symlinks: bool = True,
+ ) -> None:
+ """Change the access and modified times of a file.
+
+ Args:
+ path: (str) Path to the file.
+ times: 2-tuple of int or float numbers, of the form (atime, mtime)
+ which is used to set the access and modified times in seconds.
+ If None, both times are set to the current time.
+ ns: 2-tuple of int numbers, of the form (atime, mtime) which is
+ used to set the access and modified times in nanoseconds.
+ If None, both times are set to the current time.
+ dir_fd: If not `None`, the file descriptor of a directory,
+ with `path` being relative to this directory.
+ follow_symlinks: (bool) If `False` and `path` points to a symlink,
+ the link itself is queried instead of the linked object.
+
+ Raises:
+ TypeError: If anything other than the expected types is
+ specified in the passed `times` or `ns` tuple,
+ or if the tuple length is not equal to 2.
+ ValueError: If both times and ns are specified.
+ """
+ path = self._path_with_dir_fd(path, self.utime, dir_fd)
+ self.filesystem.utime(path, times=times, ns=ns, follow_symlinks=follow_symlinks)
+
+ def chown(
+ self,
+ path: AnyStr,
+ uid: int,
+ gid: int,
+ *,
+ dir_fd: Optional[int] = None,
+ follow_symlinks: bool = True
+ ) -> None:
+ """Set ownership of a faked file.
+
+ Args:
+ path: (str) Path to the file or directory.
+ uid: (int) Numeric uid to set the file or directory to.
+ gid: (int) Numeric gid to set the file or directory to.
+ dir_fd: (int) If not `None`, the file descriptor of a directory,
+ with `path` being relative to this directory.
+ follow_symlinks: (bool) If `False` and path points to a symlink,
+ the link itself is changed instead of the linked object.
+
+ Raises:
+ OSError: if path does not exist.
+
+ `None` is also allowed for `uid` and `gid`. This permits `os.rename`
+ to use `os.chown` even when the source file `uid` and `gid` are
+ `None` (unset).
+ """
+ path = self._path_with_dir_fd(path, self.chown, dir_fd)
+ file_object = self.filesystem.resolve(path, follow_symlinks, allow_fd=True)
+ if not isinstance(uid, int) or not isinstance(gid, int):
+ raise TypeError("An integer is required")
+ if uid != -1:
+ file_object.st_uid = uid
+ if gid != -1:
+ file_object.st_gid = gid
+
+ def mknod(
+ self,
+ path: AnyStr,
+ mode: Optional[int] = None,
+ device: int = 0,
+ *,
+ dir_fd: Optional[int] = None
+ ) -> None:
+ """Create a filesystem node named 'filename'.
+
+ Does not support device special files or named pipes as the real os
+ module does.
+
+ Args:
+ path: (str) Name of the file to create
+ mode: (int) Permissions to use and type of file to be created.
+ Default permissions are 0o666. Only the stat.S_IFREG file type
+ is supported by the fake implementation. The umask is applied
+ to this mode.
+ device: not supported in fake implementation
+ dir_fd: If not `None`, the file descriptor of a directory,
+ with `path` being relative to this directory.
+
+ Raises:
+ OSError: if called with unsupported options or the file can not be
+ created.
+ """
+ if self.filesystem.is_windows_fs:
+ raise AttributeError("module 'os' has no attribute 'mknode'")
+ if mode is None:
+ # note that a default value of 0o600 without a device type is
+ # documented - this is not how it seems to work
+ mode = S_IFREG | 0o600
+ if device or not mode & S_IFREG and not is_root():
+ self.filesystem.raise_os_error(errno.EPERM)
+
+ path = self._path_with_dir_fd(path, self.mknod, dir_fd)
+ head, tail = self.path.split(path)
+ if not tail:
+ if self.filesystem.exists(head, check_link=True):
+ self.filesystem.raise_os_error(errno.EEXIST, path)
+ self.filesystem.raise_os_error(errno.ENOENT, path)
+ if tail in (matching_string(tail, "."), matching_string(tail, "..")):
+ self.filesystem.raise_os_error(errno.ENOENT, path)
+ if self.filesystem.exists(path, check_link=True):
+ self.filesystem.raise_os_error(errno.EEXIST, path)
+ self.filesystem.add_object(
+ head,
+ FakeFile(tail, mode & ~self.filesystem.umask, filesystem=self.filesystem),
+ )
+
+ def symlink(
+ self,
+ src: AnyStr,
+ dst: AnyStr,
+ target_is_directory: bool = False,
+ *,
+ dir_fd: Optional[int] = None
+ ) -> None:
+ """Creates the specified symlink, pointed at the specified link target.
+
+ Args:
+ src: The target of the symlink.
+ dst: Path to the symlink to create.
+ target_is_directory: Currently ignored.
+ dir_fd: If not `None`, the file descriptor of a directory,
+ with `src` being relative to this directory.
+
+ Raises:
+ OSError: if the file already exists.
+ """
+ src = self._path_with_dir_fd(src, self.symlink, dir_fd)
+ self.filesystem.create_symlink(dst, src, create_missing_dirs=False)
+
+ def link(
+ self,
+ src: AnyStr,
+ dst: AnyStr,
+ *,
+ src_dir_fd: Optional[int] = None,
+ dst_dir_fd: Optional[int] = None
+ ) -> None:
+ """Create a hard link at new_path, pointing at old_path.
+
+ Args:
+ src: An existing path to the target file.
+ dst: The destination path to create a new link at.
+ src_dir_fd: If not `None`, the file descriptor of a directory,
+ with `src` being relative to this directory.
+ dst_dir_fd: If not `None`, the file descriptor of a directory,
+ with `dst` being relative to this directory.
+
+ Raises:
+ OSError: if something already exists at new_path.
+ OSError: if the parent directory doesn't exist.
+ """
+ src = self._path_with_dir_fd(src, self.link, src_dir_fd)
+ dst = self._path_with_dir_fd(dst, self.link, dst_dir_fd)
+ self.filesystem.link(src, dst)
+
+ def fsync(self, fd: int) -> None:
+ """Perform fsync for a fake file (in other words, do nothing).
+
+ Args:
+ fd: The file descriptor of the open file.
+
+ Raises:
+ OSError: file_des is an invalid file descriptor.
+ TypeError: file_des is not an integer.
+ """
+ # Throw an error if file_des isn't valid
+ if 0 <= fd < NR_STD_STREAMS:
+ self.filesystem.raise_os_error(errno.EINVAL)
+ file_object = cast(FakeFileWrapper, self.filesystem.get_open_file(fd))
+ if self.filesystem.is_windows_fs:
+ if not hasattr(file_object, "allow_update") or not file_object.allow_update:
+ self.filesystem.raise_os_error(errno.EBADF, file_object.file_path)
+
+ def fdatasync(self, fd: int) -> None:
+ """Perform fdatasync for a fake file (in other words, do nothing).
+
+ Args:
+ fd: The file descriptor of the open file.
+
+ Raises:
+ OSError: `fd` is an invalid file descriptor.
+ TypeError: `fd` is not an integer.
+ """
+ if self.filesystem.is_windows_fs or self.filesystem.is_macos:
+ raise AttributeError("module 'os' has no attribute 'fdatasync'")
+ # Throw an error if file_des isn't valid
+ if 0 <= fd < NR_STD_STREAMS:
+ self.filesystem.raise_os_error(errno.EINVAL)
+ self.filesystem.get_open_file(fd)
+
+ def sendfile(self, fd_out: int, fd_in: int, offset: int, count: int) -> int:
+ """Copy count bytes from file descriptor fd_in to file descriptor
+ fd_out starting at offset.
+
+ Args:
+ fd_out: The file descriptor of the destination file.
+ fd_in: The file descriptor of the source file.
+ offset: The offset in bytes where to start the copy in the
+ source file. If `None` (Linux only), copying is started at
+ the current position, and the position is updated.
+ count: The number of bytes to copy. If 0, all remaining bytes
+ are copied (MacOs only).
+
+ Raises:
+ OSError: If `fd_in` or `fd_out` is an invalid file descriptor.
+ TypeError: If `fd_in` or `fd_out` is not an integer.
+ TypeError: If `offset` is None under MacOs.
+ """
+ if self.filesystem.is_windows_fs:
+ raise AttributeError("module 'os' has no attribute 'sendfile'")
+ if 0 <= fd_in < NR_STD_STREAMS:
+ self.filesystem.raise_os_error(errno.EINVAL)
+ if 0 <= fd_out < NR_STD_STREAMS:
+ self.filesystem.raise_os_error(errno.EINVAL)
+ source = cast(FakeFileWrapper, self.filesystem.get_open_file(fd_in))
+ dest = cast(FakeFileWrapper, self.filesystem.get_open_file(fd_out))
+ if self.filesystem.is_macos:
+ if dest.get_object().stat_result.st_mode & 0o777000 != S_IFSOCK:
+ raise OSError("Socket operation on non-socket")
+ if offset is None:
+ if self.filesystem.is_macos:
+ raise TypeError("None is not a valid offset")
+ contents = source.read(count)
+ else:
+ position = source.tell()
+ source.seek(offset)
+ if count == 0 and self.filesystem.is_macos:
+ contents = source.read()
+ else:
+ contents = source.read(count)
+ source.seek(position)
+ if contents:
+ written = dest.write(contents)
+ dest.flush()
+ return written
+ return 0
+
+ def getuid(self) -> int:
+ """Returns the user id set in the fake filesystem.
+ If not changed using ``set_uid``, this is the uid of the real system.
+ """
+ if self.filesystem.is_windows_fs:
+ raise NameError("name 'getuid' is not defined")
+ return get_uid()
+
+ def getgid(self) -> int:
+ """Returns the group id set in the fake filesystem.
+ If not changed using ``set_gid``, this is the gid of the real system.
+ """
+ if self.filesystem.is_windows_fs:
+ raise NameError("name 'getgid' is not defined")
+ return get_gid()
+
+ def fake_functions(self, original_functions) -> Set:
+ functions = set()
+ for fn in original_functions:
+ if hasattr(self, fn.__name__):
+ functions.add(getattr(self, fn.__name__))
+ else:
+ functions.add(fn)
+ return functions
+
+ @property
+ def supports_follow_symlinks(self) -> Set[Callable]:
+ if self._supports_follow_symlinks is None:
+ self._supports_follow_symlinks = self.fake_functions(
+ self.os_module.supports_follow_symlinks
+ )
+ return self._supports_follow_symlinks
+
+ @property
+ def supports_dir_fd(self) -> Set[Callable]:
+ if self._supports_dir_fd is None:
+ self._supports_dir_fd = self.fake_functions(self.os_module.supports_dir_fd)
+ return self._supports_dir_fd
+
+ @property
+ def supports_fd(self) -> Set[Callable]:
+ if self._supports_fd is None:
+ self._supports_fd = self.fake_functions(self.os_module.supports_fd)
+ return self._supports_fd
+
+ @property
+ def supports_effective_ids(self) -> Set[Callable]:
+ if self._supports_effective_ids is None:
+ self._supports_effective_ids = self.fake_functions(
+ self.os_module.supports_effective_ids
+ )
+ return self._supports_effective_ids
+
+ def __getattr__(self, name: str) -> Any:
+ """Forwards any unfaked calls to the standard os module."""
+ return getattr(self.os_module, name)
+
+
+if sys.version_info > (3, 10):
+
+ def handle_original_call(f: Callable) -> Callable:
+ """Decorator used for real pathlib Path methods to ensure that
+ real os functions instead of faked ones are used.
+ Applied to all non-private methods of `FakeOsModule`."""
+
+ @functools.wraps(f)
+ def wrapped(*args, **kwargs):
+ if FakeOsModule.use_original:
+ # remove the `self` argument for FakeOsModule methods
+ if args and isinstance(args[0], FakeOsModule):
+ args = args[1:]
+ return getattr(os, f.__name__)(*args, **kwargs)
+ return f(*args, **kwargs)
+
+ return wrapped
+
+ for name, fn in inspect.getmembers(FakeOsModule, inspect.isfunction):
+ if not fn.__name__.startswith("_"):
+ setattr(FakeOsModule, name, handle_original_call(fn))
+
+
+@contextmanager
+def use_original_os():
+ """Temporarily use original os functions instead of faked ones.
+ Used to ensure that skipped modules do not use faked calls.
+ """
+ try:
+ FakeOsModule.use_original = True
+ yield
+ finally:
+ FakeOsModule.use_original = False
diff --git a/pyfakefs/fake_path.py b/pyfakefs/fake_path.py
new file mode 100644
index 0000000..10d6722
--- /dev/null
+++ b/pyfakefs/fake_path.py
@@ -0,0 +1,529 @@
+# Copyright 2009 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+""" Faked ``os.path`` module replacement. See ``fake_filesystem`` for usage.
+"""
+import errno
+import os
+import sys
+from stat import (
+ S_IFDIR,
+ S_IFMT,
+)
+from types import ModuleType
+from typing import (
+ List,
+ Optional,
+ Union,
+ Any,
+ Dict,
+ Tuple,
+ AnyStr,
+ overload,
+ ClassVar,
+ TYPE_CHECKING,
+)
+
+from pyfakefs.helpers import (
+ make_string_path,
+ to_string,
+ matching_string,
+)
+
+if TYPE_CHECKING:
+ from pyfakefs.fake_filesystem import FakeFilesystem
+ from pyfakefs.fake_os import FakeOsModule
+
+
+def _copy_module(old: ModuleType) -> ModuleType:
+ """Recompiles and creates new module object."""
+ saved = sys.modules.pop(old.__name__, None)
+ new = __import__(old.__name__)
+ if saved is not None:
+ sys.modules[old.__name__] = saved
+ return new
+
+
+class FakePathModule:
+ """Faked os.path module replacement.
+
+ FakePathModule should *only* be instantiated by FakeOsModule. See the
+ FakeOsModule docstring for details.
+ """
+
+ _OS_PATH_COPY: Any = _copy_module(os.path)
+
+ devnull: ClassVar[str] = ""
+ sep: ClassVar[str] = ""
+ altsep: ClassVar[Optional[str]] = None
+ linesep: ClassVar[str] = ""
+ pathsep: ClassVar[str] = ""
+
+ @staticmethod
+ def dir() -> List[str]:
+ """Return the list of patched function names. Used for patching
+ functions imported from the module.
+ """
+ dir_list = [
+ "abspath",
+ "dirname",
+ "exists",
+ "expanduser",
+ "getatime",
+ "getctime",
+ "getmtime",
+ "getsize",
+ "isabs",
+ "isdir",
+ "isfile",
+ "islink",
+ "ismount",
+ "join",
+ "lexists",
+ "normcase",
+ "normpath",
+ "realpath",
+ "relpath",
+ "split",
+ "splitdrive",
+ "samefile",
+ ]
+ if sys.version_info >= (3, 12):
+ dir_list += ["isjunction", "splitroot"]
+ return dir_list
+
+ def __init__(self, filesystem: "FakeFilesystem", os_module: "FakeOsModule"):
+ """Init.
+
+ Args:
+ filesystem: FakeFilesystem used to provide file system information
+ """
+ self.filesystem = filesystem
+ self._os_path = self._OS_PATH_COPY
+ self._os_path.os = self.os = os_module # type: ignore[attr-defined]
+ self.reset(filesystem)
+
+ @classmethod
+ def reset(cls, filesystem: "FakeFilesystem") -> None:
+ cls.sep = filesystem.path_separator
+ cls.altsep = filesystem.alternative_path_separator
+ cls.linesep = filesystem.line_separator()
+ cls.devnull = "nul" if filesystem.is_windows_fs else "/dev/null"
+ cls.pathsep = ";" if filesystem.is_windows_fs else ":"
+
+ def exists(self, path: AnyStr) -> bool:
+ """Determine whether the file object exists within the fake filesystem.
+
+ Args:
+ path: The path to the file object.
+
+ Returns:
+ (bool) `True` if the file exists.
+ """
+ return self.filesystem.exists(path)
+
+ def lexists(self, path: AnyStr) -> bool:
+ """Test whether a path exists. Returns True for broken symbolic links.
+
+ Args:
+ path: path to the symlink object.
+
+ Returns:
+ bool (if file exists).
+ """
+ return self.filesystem.exists(path, check_link=True)
+
+ def getsize(self, path: AnyStr):
+ """Return the file object size in bytes.
+
+ Args:
+ path: path to the file object.
+
+ Returns:
+ file size in bytes.
+ """
+ file_obj = self.filesystem.resolve(path)
+ if (
+ self.filesystem.ends_with_path_separator(path)
+ and S_IFMT(file_obj.st_mode) != S_IFDIR
+ ):
+ error_nr = errno.EINVAL if self.filesystem.is_windows_fs else errno.ENOTDIR
+ self.filesystem.raise_os_error(error_nr, path)
+ return file_obj.st_size
+
+ def isabs(self, path: AnyStr) -> bool:
+ """Return True if path is an absolute pathname."""
+ if self.filesystem.is_windows_fs:
+ path = self.splitdrive(path)[1]
+ path = make_string_path(path)
+ return self.filesystem.starts_with_sep(path)
+
+ def isdir(self, path: AnyStr) -> bool:
+ """Determine if path identifies a directory."""
+ return self.filesystem.isdir(path)
+
+ def isfile(self, path: AnyStr) -> bool:
+ """Determine if path identifies a regular file."""
+ return self.filesystem.isfile(path)
+
+ def islink(self, path: AnyStr) -> bool:
+ """Determine if path identifies a symbolic link.
+
+ Args:
+ path: Path to filesystem object.
+
+ Returns:
+ `True` if path points to a symbolic link.
+
+ Raises:
+ TypeError: if path is None.
+ """
+ return self.filesystem.islink(path)
+
+ if sys.version_info >= (3, 12):
+
+ def isjunction(self, path: AnyStr) -> bool:
+ """Returns False. Junctions are never faked."""
+ return self.filesystem.isjunction(path)
+
+ def splitroot(self, path: AnyStr):
+ """Split a pathname into drive, root and tail.
+ Implementation taken from ntpath and posixpath.
+ """
+ return self.filesystem.splitroot(path)
+
+ def getmtime(self, path: AnyStr) -> float:
+ """Returns the modification time of the fake file.
+
+ Args:
+ path: the path to fake file.
+
+ Returns:
+ (int, float) the modification time of the fake file
+ in number of seconds since the epoch.
+
+ Raises:
+ OSError: if the file does not exist.
+ """
+ try:
+ file_obj = self.filesystem.resolve(path)
+ return file_obj.st_mtime
+ except OSError:
+ self.filesystem.raise_os_error(errno.ENOENT, winerror=3)
+
+ def getatime(self, path: AnyStr) -> float:
+ """Returns the last access time of the fake file.
+
+ Note: Access time is not set automatically in fake filesystem
+ on access.
+
+ Args:
+ path: the path to fake file.
+
+ Returns:
+ (int, float) the access time of the fake file in number of seconds
+ since the epoch.
+
+ Raises:
+ OSError: if the file does not exist.
+ """
+ try:
+ file_obj = self.filesystem.resolve(path)
+ except OSError:
+ self.filesystem.raise_os_error(errno.ENOENT)
+ return file_obj.st_atime
+
+ def getctime(self, path: AnyStr) -> float:
+ """Returns the creation time of the fake file.
+
+ Args:
+ path: the path to fake file.
+
+ Returns:
+ (int, float) the creation time of the fake file in number of
+ seconds since the epoch.
+
+ Raises:
+ OSError: if the file does not exist.
+ """
+ try:
+ file_obj = self.filesystem.resolve(path)
+ except OSError:
+ self.filesystem.raise_os_error(errno.ENOENT)
+ return file_obj.st_ctime
+
+ def abspath(self, path: AnyStr) -> AnyStr:
+ """Return the absolute version of a path."""
+
+ def getcwd():
+ """Return the current working directory."""
+ # pylint: disable=undefined-variable
+ if isinstance(path, bytes):
+ return self.os.getcwdb()
+ else:
+ return self.os.getcwd()
+
+ path = make_string_path(path)
+ if not self.isabs(path):
+ path = self.join(getcwd(), path)
+ elif self.filesystem.is_windows_fs and self.filesystem.starts_with_sep(path):
+ cwd = getcwd()
+ if self.filesystem.starts_with_drive_letter(cwd):
+ path = self.join(cwd[:2], path)
+ return self.normpath(path)
+
+ def join(self, *p: AnyStr) -> AnyStr:
+ """Return the completed path with a separator of the parts."""
+ return self.filesystem.joinpaths(*p)
+
+ def split(self, path: AnyStr) -> Tuple[AnyStr, AnyStr]:
+ """Split the path into the directory and the filename of the path."""
+ return self.filesystem.splitpath(path)
+
+ def splitdrive(self, path: AnyStr) -> Tuple[AnyStr, AnyStr]:
+ """Split the path into the drive part and the rest of the path, if
+ supported."""
+ return self.filesystem.splitdrive(path)
+
+ def normpath(self, path: AnyStr) -> AnyStr:
+ """Normalize path, eliminating double slashes, etc."""
+ return self.filesystem.normpath(path)
+
+ def normcase(self, path: AnyStr) -> AnyStr:
+ """Convert to lower case under windows, replaces additional path
+ separator."""
+ path = self.filesystem.normcase(path)
+ if self.filesystem.is_windows_fs:
+ path = path.lower()
+ return path
+
+ def relpath(self, path: AnyStr, start: Optional[AnyStr] = None) -> AnyStr:
+ """We mostly rely on the native implementation and adapt the
+ path separator."""
+ if not path:
+ raise ValueError("no path specified")
+ path = make_string_path(path)
+ path = self.filesystem.replace_windows_root(path)
+ sep = matching_string(path, self.filesystem.path_separator)
+ if start is not None:
+ start = make_string_path(start)
+ else:
+ start = matching_string(path, self.filesystem.cwd)
+ start = self.filesystem.replace_windows_root(start)
+ system_sep = matching_string(path, self._os_path.sep)
+ if self.filesystem.alternative_path_separator is not None:
+ altsep = matching_string(path, self.filesystem.alternative_path_separator)
+ path = path.replace(altsep, system_sep)
+ start = start.replace(altsep, system_sep)
+ path = path.replace(sep, system_sep)
+ start = start.replace(sep, system_sep)
+ path = self._os_path.relpath(path, start)
+ return path.replace(system_sep, sep)
+
+ def realpath(self, filename: AnyStr, strict: Optional[bool] = None) -> AnyStr:
+ """Return the canonical path of the specified filename, eliminating any
+ symbolic links encountered in the path.
+ """
+ if strict is not None and sys.version_info < (3, 10):
+ raise TypeError("realpath() got an unexpected " "keyword argument 'strict'")
+ if strict:
+ # raises in strict mode if the file does not exist
+ self.filesystem.resolve(filename)
+ if self.filesystem.is_windows_fs:
+ return self.abspath(filename)
+ filename = make_string_path(filename)
+ path, ok = self._join_real_path(filename[:0], filename, {})
+ path = self.abspath(path)
+ return path
+
+ def samefile(self, path1: AnyStr, path2: AnyStr) -> bool:
+ """Return whether path1 and path2 point to the same file.
+
+ Args:
+ path1: first file path or path object (Python >=3.6)
+ path2: second file path or path object (Python >=3.6)
+
+ Raises:
+ OSError: if one of the paths does not point to an existing
+ file system object.
+ """
+ stat1 = self.filesystem.stat(path1)
+ stat2 = self.filesystem.stat(path2)
+ return stat1.st_ino == stat2.st_ino and stat1.st_dev == stat2.st_dev
+
+ @overload
+ def _join_real_path(
+ self, path: str, rest: str, seen: Dict[str, Optional[str]]
+ ) -> Tuple[str, bool]:
+ ...
+
+ @overload
+ def _join_real_path(
+ self, path: bytes, rest: bytes, seen: Dict[bytes, Optional[bytes]]
+ ) -> Tuple[bytes, bool]:
+ ...
+
+ def _join_real_path(
+ self, path: AnyStr, rest: AnyStr, seen: Dict[AnyStr, Optional[AnyStr]]
+ ) -> Tuple[AnyStr, bool]:
+ """Join two paths, normalizing and eliminating any symbolic links
+ encountered in the second path.
+ Taken from Python source and adapted.
+ """
+ curdir = matching_string(path, ".")
+ pardir = matching_string(path, "..")
+
+ sep = self.filesystem.get_path_separator(path)
+ if self.isabs(rest):
+ rest = rest[1:]
+ path = sep
+
+ while rest:
+ name, _, rest = rest.partition(sep)
+ if not name or name == curdir:
+ # current dir
+ continue
+ if name == pardir:
+ # parent dir
+ if path:
+ path, name = self.filesystem.splitpath(path)
+ if name == pardir:
+ path = self.filesystem.joinpaths(path, pardir, pardir)
+ else:
+ path = pardir
+ continue
+ newpath = self.filesystem.joinpaths(path, name)
+ if not self.filesystem.islink(newpath):
+ path = newpath
+ continue
+ # Resolve the symbolic link
+ if newpath in seen:
+ # Already seen this path
+ seen_path = seen[newpath]
+ if seen_path is not None:
+ # use cached value
+ path = seen_path
+ continue
+ # The symlink is not resolved, so we must have a symlink loop.
+ # Return already resolved part + rest of the path unchanged.
+ return self.filesystem.joinpaths(newpath, rest), False
+ seen[newpath] = None # not resolved symlink
+ path, ok = self._join_real_path(
+ path,
+ matching_string(path, self.filesystem.readlink(newpath)),
+ seen,
+ )
+ if not ok:
+ return self.filesystem.joinpaths(path, rest), False
+ seen[newpath] = path # resolved symlink
+ return path, True
+
+ def dirname(self, path: AnyStr) -> AnyStr:
+ """Returns the first part of the result of `split()`."""
+ return self.split(path)[0]
+
+ def expanduser(self, path: AnyStr) -> AnyStr:
+ """Return the argument with an initial component of ~ or ~user
+ replaced by that user's home directory.
+ """
+ path = self._os_path.expanduser(path)
+ return path.replace(
+ matching_string(path, self._os_path.sep),
+ matching_string(path, self.sep),
+ )
+
+ def ismount(self, path: AnyStr) -> bool:
+ """Return true if the given path is a mount point.
+
+ Args:
+ path: Path to filesystem object to be checked
+
+ Returns:
+ `True` if path is a mount point added to the fake file system.
+ Under Windows also returns True for drive and UNC roots
+ (independent of their existence).
+ """
+ if not path:
+ return False
+ path_str = to_string(make_string_path(path))
+ normed_path = self.filesystem.absnormpath(path_str)
+ sep = self.filesystem.path_separator
+ if self.filesystem.is_windows_fs:
+ path_seps: Union[Tuple[str, Optional[str]], Tuple[str]]
+ if self.filesystem.alternative_path_separator is not None:
+ path_seps = (sep, self.filesystem.alternative_path_separator)
+ else:
+ path_seps = (sep,)
+ drive, rest = self.filesystem.splitdrive(normed_path)
+ if drive and drive[:1] in path_seps:
+ return (not rest) or (rest in path_seps)
+ if rest in path_seps:
+ return True
+ for mount_point in self.filesystem.mount_points:
+ if to_string(normed_path).rstrip(sep) == to_string(mount_point).rstrip(sep):
+ return True
+ return False
+
+ def __getattr__(self, name: str) -> Any:
+ """Forwards any non-faked calls to the real os.path."""
+ return getattr(self._os_path, name)
+
+
+if sys.platform == "win32":
+
+ class FakeNtModule:
+ """Under windows, a few function of `os.path` are taken from the `nt` module
+ for performance reasons. These are patched here.
+ """
+
+ @staticmethod
+ def dir():
+ if sys.version_info >= (3, 12):
+ return ["_path_exists", "_path_isfile", "_path_isdir", "_path_islink"]
+ else:
+ return ["_isdir"]
+
+ def __init__(self, filesystem: "FakeFilesystem"):
+ """Init.
+
+ Args:
+ filesystem: FakeFilesystem used to provide file system information
+ """
+ import nt # type:ignore[import]
+
+ self.filesystem = filesystem
+ self.nt_module: Any = nt
+
+ if sys.version_info >= (3, 12):
+
+ def _path_isdir(self, path: AnyStr) -> bool:
+ return self.filesystem.isdir(path)
+
+ def _path_isfile(self, path: AnyStr) -> bool:
+ return self.filesystem.isfile(path)
+
+ def _path_islink(self, path: AnyStr) -> bool:
+ return self.filesystem.islink(path)
+
+ def _path_exists(self, path: AnyStr) -> bool:
+ return self.filesystem.exists(path)
+
+ else:
+
+ def _isdir(self, path: AnyStr) -> bool:
+ return self.filesystem.isdir(path)
+
+ def __getattr__(self, name: str) -> Any:
+ """Forwards any non-faked calls to the real nt module."""
+ return getattr(self.nt_module, name)
diff --git a/pyfakefs/fake_pathlib.py b/pyfakefs/fake_pathlib.py
index 8868558..6e096d1 100644
--- a/pyfakefs/fake_pathlib.py
+++ b/pyfakefs/fake_pathlib.py
@@ -31,25 +31,39 @@ get the properties of the underlying fake filesystem.
import errno
import fnmatch
import functools
+import inspect
+import ntpath
import os
import pathlib
-from pathlib import PurePath
+import posixpath
import re
import sys
+from pathlib import PurePath
+from typing import Callable
from urllib.parse import quote_from_bytes as urlquote_from_bytes
from pyfakefs import fake_scandir
from pyfakefs.extra_packages import use_scandir
-from pyfakefs.fake_filesystem import FakeFileOpen, FakeFilesystem
+from pyfakefs.fake_filesystem import FakeFilesystem
+from pyfakefs.fake_open import FakeFileOpen
+from pyfakefs.fake_os import FakeOsModule, use_original_os
+from pyfakefs.helpers import IS_PYPY
def init_module(filesystem):
"""Initializes the fake module with the fake file system."""
# pylint: disable=protected-access
FakePath.filesystem = filesystem
- FakePathlibModule.PureWindowsPath._flavour = _FakeWindowsFlavour(
- filesystem)
- FakePathlibModule.PurePosixPath._flavour = _FakePosixFlavour(filesystem)
+ if sys.version_info < (3, 12):
+ FakePathlibModule.PureWindowsPath._flavour = _FakeWindowsFlavour(filesystem)
+ FakePathlibModule.PurePosixPath._flavour = _FakePosixFlavour(filesystem)
+ else:
+ # in Python 3.12, the flavour is no longer an own class,
+ # but points to the os-specific path module (posixpath/ntpath)
+ fake_os = FakeOsModule(filesystem)
+ fake_path = fake_os.path
+ FakePathlibModule.PureWindowsPath._flavour = fake_path
+ FakePathlibModule.PurePosixPath._flavour = fake_path
def _wrap_strfunc(strfunc):
@@ -63,8 +77,7 @@ def _wrap_strfunc(strfunc):
def _wrap_binary_strfunc(strfunc):
@functools.wraps(strfunc)
def _wrapped(pathobj1, pathobj2, *args):
- return strfunc(
- pathobj1.filesystem, str(pathobj1), str(pathobj2), *args)
+ return strfunc(pathobj1.filesystem, str(pathobj1), str(pathobj2), *args)
return staticmethod(_wrapped)
@@ -72,53 +85,59 @@ def _wrap_binary_strfunc(strfunc):
def _wrap_binary_strfunc_reverse(strfunc):
@functools.wraps(strfunc)
def _wrapped(pathobj1, pathobj2, *args):
- return strfunc(
- pathobj2.filesystem, str(pathobj2), str(pathobj1), *args)
+ return strfunc(pathobj2.filesystem, str(pathobj2), str(pathobj1), *args)
return staticmethod(_wrapped)
try:
- accessor = pathlib._Accessor # type: ignore [attr-defined]
+ accessor = pathlib._Accessor # type: ignore[attr-defined]
except AttributeError:
accessor = object
-class _FakeAccessor(accessor): # type: ignore [valid-type, misc]
- """Accessor which forwards some of the functions to FakeFilesystem methods.
+class _FakeAccessor(accessor): # type: ignore[valid-type, misc]
+ """Accessor which forwards some of the functions to FakeFilesystem
+ methods.
"""
stat = _wrap_strfunc(FakeFilesystem.stat)
lstat = _wrap_strfunc(
- lambda fs, path: FakeFilesystem.stat(fs, path, follow_symlinks=False))
+ lambda fs, path: FakeFilesystem.stat(fs, path, follow_symlinks=False)
+ )
listdir = _wrap_strfunc(FakeFilesystem.listdir)
if use_scandir:
scandir = _wrap_strfunc(fake_scandir.scandir)
- chmod = _wrap_strfunc(FakeFilesystem.chmod)
-
if hasattr(os, "lchmod"):
- lchmod = _wrap_strfunc(lambda fs, path, mode: FakeFilesystem.chmod(
- fs, path, mode, follow_symlinks=False))
+ lchmod = _wrap_strfunc(
+ lambda fs, path, mode: FakeFilesystem.chmod(
+ fs, path, mode, follow_symlinks=False
+ )
+ )
else:
- def lchmod(self, pathobj, *args, **kwargs):
+
+ def lchmod(self, pathobj, *args, **kwargs):
"""Raises not implemented for Windows systems."""
raise NotImplementedError("lchmod() not available on this system")
- def chmod(self, pathobj, *args, **kwargs):
- if "follow_symlinks" in kwargs:
- if sys.version_info < (3, 10):
- raise TypeError("chmod() got an unexpected keyword "
- "argument 'follow_synlinks'")
- if (not kwargs["follow_symlinks"] and
- os.chmod not in os.supports_follow_symlinks):
- raise NotImplementedError(
- "`follow_symlinks` for chmod() is not available "
- "on this system")
- return pathobj.filesystem.chmod(str(pathobj), *args, **kwargs)
+ def chmod(self, pathobj, *args, **kwargs):
+ if "follow_symlinks" in kwargs:
+ if sys.version_info < (3, 10):
+ raise TypeError(
+ "chmod() got an unexpected keyword " "argument 'follow_symlinks'"
+ )
+
+ if not kwargs["follow_symlinks"] and (
+ os.chmod not in os.supports_follow_symlinks or IS_PYPY
+ ):
+ raise NotImplementedError(
+ "`follow_symlinks` for chmod() is not available " "on this system"
+ )
+ return pathobj.filesystem.chmod(str(pathobj), *args, **kwargs)
mkdir = _wrap_strfunc(FakeFilesystem.makedir)
@@ -130,22 +149,29 @@ class _FakeAccessor(accessor): # type: ignore [valid-type, misc]
replace = _wrap_binary_strfunc(
lambda fs, old_path, new_path: FakeFilesystem.rename(
- fs, old_path, new_path, force_replace=True))
+ fs, old_path, new_path, force_replace=True
+ )
+ )
symlink = _wrap_binary_strfunc_reverse(
- lambda fs, file_path, link_target, target_is_directory:
- FakeFilesystem.create_symlink(fs, file_path, link_target,
- create_missing_dirs=False))
+ lambda fs, fpath, target, target_is_dir: FakeFilesystem.create_symlink(
+ fs, fpath, target, create_missing_dirs=False
+ )
+ )
if (3, 8) <= sys.version_info:
link_to = _wrap_binary_strfunc(
- lambda fs, file_path, link_target:
- FakeFilesystem.link(fs, file_path, link_target))
+ lambda fs, file_path, link_target: FakeFilesystem.link(
+ fs, file_path, link_target
+ )
+ )
if sys.version_info >= (3, 10):
link = _wrap_binary_strfunc(
- lambda fs, file_path, link_target:
- FakeFilesystem.link(fs, file_path, link_target))
+ lambda fs, file_path, link_target: FakeFilesystem.link(
+ fs, file_path, link_target
+ )
+ )
# this will use the fake filesystem because os is patched
def getcwd(self):
@@ -158,312 +184,322 @@ class _FakeAccessor(accessor): # type: ignore [valid-type, misc]
_fake_accessor = _FakeAccessor()
-flavour = pathlib._Flavour # type: ignore [attr-defined]
-
+if sys.version_info < (3, 12):
+ flavour = pathlib._Flavour # type: ignore[attr-defined]
+
+ class _FakeFlavour(flavour): # type: ignore[valid-type, misc]
+ """Fake Flavour implementation used by PurePath and _Flavour"""
+
+ filesystem = None
+ sep = "/"
+ altsep = None
+ has_drv = False
+
+ ext_namespace_prefix = "\\\\?\\"
+
+ drive_letters = {chr(x) for x in range(ord("a"), ord("z") + 1)} | {
+ chr(x) for x in range(ord("A"), ord("Z") + 1)
+ }
+
+ def __init__(self, filesystem):
+ self.filesystem = filesystem
+ self.sep = filesystem.path_separator
+ self.altsep = filesystem.alternative_path_separator
+ self.has_drv = filesystem.is_windows_fs
+ super(_FakeFlavour, self).__init__()
+
+ @staticmethod
+ def _split_extended_path(path, ext_prefix=ext_namespace_prefix):
+ prefix = ""
+ if path.startswith(ext_prefix):
+ prefix = path[:4]
+ path = path[4:]
+ if path.startswith("UNC\\"):
+ prefix += path[:3]
+ path = "\\" + path[3:]
+ return prefix, path
+
+ def _splitroot_with_drive(self, path, sep):
+ first = path[0:1]
+ second = path[1:2]
+ if second == sep and first == sep:
+ # extended paths should also disable the collapsing of "."
+ # components (according to MSDN docs).
+ prefix, path = self._split_extended_path(path)
+ first = path[0:1]
+ second = path[1:2]
+ else:
+ prefix = ""
+ third = path[2:3]
+ if second == sep and first == sep and third != sep:
+ # is a UNC path:
+ # vvvvvvvvvvvvvvvvvvvvv root
+ # \\machine\mountpoint\directory\etc\...
+ # directory ^^^^^^^^^^^^^^
+ index = path.find(sep, 2)
+ if index != -1:
+ index2 = path.find(sep, index + 1)
+ # a UNC path can't have two slashes in a row
+ # (after the initial two)
+ if index2 != index + 1:
+ if index2 == -1:
+ index2 = len(path)
+ if prefix:
+ return prefix + path[1:index2], sep, path[index2 + 1 :]
+ return path[:index2], sep, path[index2 + 1 :]
+ drv = root = ""
+ if second == ":" and first in self.drive_letters:
+ drv = path[:2]
+ path = path[2:]
+ first = third
+ if first == sep:
+ root = first
+ path = path.lstrip(sep)
+ return prefix + drv, root, path
+
+ @staticmethod
+ def _splitroot_posix(path, sep):
+ if path and path[0] == sep:
+ stripped_part = path.lstrip(sep)
+ if len(path) - len(stripped_part) == 2:
+ return "", sep * 2, stripped_part
+ return "", sep, stripped_part
+ else:
+ return "", "", path
+
+ def splitroot(self, path, sep=None):
+ """Split path into drive, root and rest."""
+ if sep is None:
+ sep = self.filesystem.path_separator
+ if self.filesystem.is_windows_fs:
+ return self._splitroot_with_drive(path, sep)
+ return self._splitroot_posix(path, sep)
+
+ def casefold(self, path):
+ """Return the lower-case version of s for a Windows filesystem."""
+ if self.filesystem.is_windows_fs:
+ return path.lower()
+ return path
-class _FakeFlavour(flavour): # type: ignore [valid-type, misc]
- """Fake Flavour implementation used by PurePath and _Flavour"""
+ def casefold_parts(self, parts):
+ """Return the lower-case version of parts for a Windows filesystem."""
+ if self.filesystem.is_windows_fs:
+ return [p.lower() for p in parts]
+ return parts
- filesystem = None
- sep = '/'
- altsep = None
- has_drv = False
+ def _resolve_posix(self, path, strict):
+ sep = self.sep
+ seen = {}
- ext_namespace_prefix = '\\\\?\\'
+ def _resolve(path, rest):
+ if rest.startswith(sep):
+ path = ""
- drive_letters = (
- set(chr(x) for x in range(ord('a'), ord('z') + 1)) |
- set(chr(x) for x in range(ord('A'), ord('Z') + 1))
- )
-
- def __init__(self, filesystem):
- self.filesystem = filesystem
- self.sep = filesystem.path_separator
- self.altsep = filesystem.alternative_path_separator
- self.has_drv = filesystem.is_windows_fs
- super(_FakeFlavour, self).__init__()
-
- @staticmethod
- def _split_extended_path(path, ext_prefix=ext_namespace_prefix):
- prefix = ''
- if path.startswith(ext_prefix):
- prefix = path[:4]
- path = path[4:]
- if path.startswith('UNC\\'):
- prefix += path[:3]
- path = '\\' + path[3:]
- return prefix, path
-
- def _splitroot_with_drive(self, path, sep):
- first = path[0:1]
- second = path[1:2]
- if second == sep and first == sep:
- # extended paths should also disable the collapsing of "."
- # components (according to MSDN docs).
- prefix, path = self._split_extended_path(path)
- first = path[0:1]
- second = path[1:2]
- else:
- prefix = ''
- third = path[2:3]
- if second == sep and first == sep and third != sep:
- # is a UNC path:
- # vvvvvvvvvvvvvvvvvvvvv root
- # \\machine\mountpoint\directory\etc\...
- # directory ^^^^^^^^^^^^^^
- index = path.find(sep, 2)
- if index != -1:
- index2 = path.find(sep, index + 1)
- # a UNC path can't have two slashes in a row
- # (after the initial two)
- if index2 != index + 1:
- if index2 == -1:
- index2 = len(path)
- if prefix:
- return prefix + path[1:index2], sep, path[index2 + 1:]
- return path[:index2], sep, path[index2 + 1:]
- drv = root = ''
- if second == ':' and first in self.drive_letters:
- drv = path[:2]
- path = path[2:]
- first = third
- if first == sep:
- root = first
- path = path.lstrip(sep)
- return prefix + drv, root, path
-
- @staticmethod
- def _splitroot_posix(path, sep):
- if path and path[0] == sep:
- stripped_part = path.lstrip(sep)
- if len(path) - len(stripped_part) == 2:
- return '', sep * 2, stripped_part
- return '', sep, stripped_part
- else:
- return '', '', path
-
- def splitroot(self, path, sep=None):
- """Split path into drive, root and rest."""
- if sep is None:
- sep = self.filesystem.path_separator
- if self.filesystem.is_windows_fs:
- return self._splitroot_with_drive(path, sep)
- return self._splitroot_posix(path, sep)
-
- def casefold(self, path):
- """Return the lower-case version of s for a Windows filesystem."""
- if self.filesystem.is_windows_fs:
- return path.lower()
- return path
-
- def casefold_parts(self, parts):
- """Return the lower-case version of parts for a Windows filesystem."""
- if self.filesystem.is_windows_fs:
- return [p.lower() for p in parts]
- return parts
-
- def _resolve_posix(self, path, strict):
- sep = self.sep
- seen = {}
-
- def _resolve(path, rest):
- if rest.startswith(sep):
- path = ''
-
- for name in rest.split(sep):
- if not name or name == '.':
- # current dir
- continue
- if name == '..':
- # parent dir
- path, _, _ = path.rpartition(sep)
- continue
- newpath = path + sep + name
- if newpath in seen:
- # Already seen this path
- path = seen[newpath]
- if path is not None:
- # use cached value
+ for name in rest.split(sep):
+ if not name or name == ".":
+ # current dir
+ continue
+ if name == "..":
+ # parent dir
+ path, _, _ = path.rpartition(sep)
continue
- # The symlink is not resolved, so we must have
- # a symlink loop.
- raise RuntimeError("Symlink loop from %r" % newpath)
- # Resolve the symbolic link
+ newpath = path + sep + name
+ if newpath in seen:
+ # Already seen this path
+ path = seen[newpath]
+ if path is not None:
+ # use cached value
+ continue
+ # The symlink is not resolved, so we must have
+ # a symlink loop.
+ raise RuntimeError("Symlink loop from %r" % newpath)
+ # Resolve the symbolic link
+ try:
+ target = self.filesystem.readlink(newpath)
+ except OSError as e:
+ if e.errno != errno.EINVAL and strict:
+ raise
+ # Not a symlink, or non-strict mode. We just leave the path
+ # untouched.
+ path = newpath
+ else:
+ seen[newpath] = None # not resolved symlink
+ path = _resolve(path, target)
+ seen[newpath] = path # resolved symlink
+
+ return path
+
+ # NOTE: according to POSIX, getcwd() cannot contain path components
+ # which are symlinks.
+ base = "" if path.is_absolute() else self.filesystem.cwd
+ return _resolve(base, str(path)) or sep
+
+ def _resolve_windows(self, path, strict):
+ path = str(path)
+ if not path:
+ return os.getcwd()
+ previous_s = None
+ if strict:
+ if not self.filesystem.exists(path):
+ self.filesystem.raise_os_error(errno.ENOENT, path)
+ return self.filesystem.resolve_path(path)
+ else:
+ while True:
+ try:
+ path = self.filesystem.resolve_path(path)
+ except OSError:
+ previous_s = path
+ path = self.filesystem.splitpath(path)[0]
+ else:
+ if previous_s is None:
+ return path
+ return self.filesystem.joinpaths(
+ path, os.path.basename(previous_s)
+ )
+
+ def resolve(self, path, strict):
+ """Make the path absolute, resolving any symlinks."""
+ if self.filesystem.is_windows_fs:
+ return self._resolve_windows(path, strict)
+ return self._resolve_posix(path, strict)
+
+ def gethomedir(self, username):
+ """Return the home directory of the current user."""
+ if not username:
try:
- target = self.filesystem.readlink(newpath)
- except OSError as e:
- if e.errno != errno.EINVAL and strict:
- raise
- # Not a symlink, or non-strict mode. We just leave the path
- # untouched.
- path = newpath
- else:
- seen[newpath] = None # not resolved symlink
- path = _resolve(path, target)
- seen[newpath] = path # resolved symlink
+ return os.environ["HOME"]
+ except KeyError:
+ import pwd
- return path
+ return pwd.getpwuid(os.getuid()).pw_dir
+ else:
+ import pwd
- # NOTE: according to POSIX, getcwd() cannot contain path components
- # which are symlinks.
- base = '' if path.is_absolute() else self.filesystem.cwd
- return _resolve(base, str(path)) or sep
+ try:
+ return pwd.getpwnam(username).pw_dir
+ except KeyError:
+ raise RuntimeError(
+ "Can't determine home directory " "for %r" % username
+ )
+
+ class _FakeWindowsFlavour(_FakeFlavour):
+ """Flavour used by PureWindowsPath with some Windows specific
+ implementations independent of FakeFilesystem properties.
+ """
- def _resolve_windows(self, path, strict):
- path = str(path)
- if not path:
- return os.getcwd()
- previous_s = None
- if strict:
- if not self.filesystem.exists(path):
- self.filesystem.raise_os_error(errno.ENOENT, path)
- return self.filesystem.resolve_path(path)
- else:
- while True:
+ reserved_names = (
+ {"CON", "PRN", "AUX", "NUL"}
+ | {"COM%d" % i for i in range(1, 10)}
+ | {"LPT%d" % i for i in range(1, 10)}
+ )
+ pathmod = ntpath
+
+ def is_reserved(self, parts):
+ """Return True if the path is considered reserved under Windows."""
+
+ # NOTE: the rules for reserved names seem somewhat complicated
+ # (e.g. r"..\NUL" is reserved but not r"foo\NUL").
+ # We err on the side of caution and return True for paths which are
+ # not considered reserved by Windows.
+ if not parts:
+ return False
+ if self.filesystem.is_windows_fs and parts[0].startswith("\\\\"):
+ # UNC paths are never reserved
+ return False
+ return parts[-1].partition(".")[0].upper() in self.reserved_names
+
+ def make_uri(self, path):
+ """Return a file URI for the given path"""
+
+ # Under Windows, file URIs use the UTF-8 encoding.
+ # original version, not faked
+ drive = path.drive
+ if len(drive) == 2 and drive[1] == ":":
+ # It's a path on a local drive => 'file:///c:/a/b'
+ rest = path.as_posix()[2:].lstrip("/")
+ return "file:///%s/%s" % (
+ drive,
+ urlquote_from_bytes(rest.encode("utf-8")),
+ )
+ else:
+ # It's a path on a network drive => 'file://host/share/a/b'
+ return "file:" + urlquote_from_bytes(path.as_posix().encode("utf-8"))
+
+ def gethomedir(self, username):
+ """Return the home directory of the current user."""
+
+ # original version, not faked
+ if "HOME" in os.environ:
+ userhome = os.environ["HOME"]
+ elif "USERPROFILE" in os.environ:
+ userhome = os.environ["USERPROFILE"]
+ elif "HOMEPATH" in os.environ:
try:
- path = self.filesystem.resolve_path(path)
- except OSError:
- previous_s = path
- path = self.filesystem.splitpath(path)[0]
- else:
- if previous_s is None:
- return path
- return self.filesystem.joinpaths(
- path, os.path.basename(previous_s))
-
- def resolve(self, path, strict):
- """Make the path absolute, resolving any symlinks."""
- if self.filesystem.is_windows_fs:
- return self._resolve_windows(path, strict)
- return self._resolve_posix(path, strict)
-
- def gethomedir(self, username):
- """Return the home directory of the current user."""
- if not username:
- try:
- return os.environ['HOME']
- except KeyError:
- import pwd
- return pwd.getpwuid(os.getuid()).pw_dir
- else:
- import pwd
- try:
- return pwd.getpwnam(username).pw_dir
- except KeyError:
- raise RuntimeError("Can't determine home directory "
- "for %r" % username)
+ drv = os.environ["HOMEDRIVE"]
+ except KeyError:
+ drv = ""
+ userhome = drv + os.environ["HOMEPATH"]
+ else:
+ raise RuntimeError("Can't determine home directory")
+
+ if username:
+ # Try to guess user home directory. By default all users
+ # directories are located in the same place and are named by
+ # corresponding usernames. If current user home directory points
+ # to nonstandard place, this guess is likely wrong.
+ if os.environ["USERNAME"] != username:
+ drv, root, parts = self.parse_parts((userhome,))
+ if parts[-1] != os.environ["USERNAME"]:
+ raise RuntimeError(
+ "Can't determine home directory " "for %r" % username
+ )
+ parts[-1] = username
+ if drv or root:
+ userhome = drv + root + self.join(parts[1:])
+ else:
+ userhome = self.join(parts)
+ return userhome
+
+ def compile_pattern(self, pattern):
+ return re.compile(fnmatch.translate(pattern), re.IGNORECASE).fullmatch
+
+ class _FakePosixFlavour(_FakeFlavour):
+ """Flavour used by PurePosixPath with some Unix specific implementations
+ independent of FakeFilesystem properties.
+ """
+ pathmod = posixpath
-class _FakeWindowsFlavour(_FakeFlavour):
- """Flavour used by PureWindowsPath with some Windows specific
- implementations independent of FakeFilesystem properties.
- """
- reserved_names = (
- {'CON', 'PRN', 'AUX', 'NUL'} |
- {'COM%d' % i for i in range(1, 10)} |
- {'LPT%d' % i for i in range(1, 10)}
- )
+ def is_reserved(self, parts):
+ return False
- def is_reserved(self, parts):
- """Return True if the path is considered reserved under Windows."""
+ def make_uri(self, path):
+ # We represent the path using the local filesystem encoding,
+ # for portability to other applications.
+ bpath = bytes(path)
+ return "file://" + urlquote_from_bytes(bpath)
- # NOTE: the rules for reserved names seem somewhat complicated
- # (e.g. r"..\NUL" is reserved but not r"foo\NUL").
- # We err on the side of caution and return True for paths which are
- # not considered reserved by Windows.
- if not parts:
- return False
- if self.filesystem.is_windows_fs and parts[0].startswith('\\\\'):
- # UNC paths are never reserved
- return False
- return parts[-1].partition('.')[0].upper() in self.reserved_names
-
- def make_uri(self, path):
- """Return a file URI for the given path"""
-
- # Under Windows, file URIs use the UTF-8 encoding.
- # original version, not faked
- drive = path.drive
- if len(drive) == 2 and drive[1] == ':':
- # It's a path on a local drive => 'file:///c:/a/b'
- rest = path.as_posix()[2:].lstrip('/')
- return 'file:///%s/%s' % (
- drive, urlquote_from_bytes(rest.encode('utf-8')))
- else:
- # It's a path on a network drive => 'file://host/share/a/b'
- return ('file:' +
- urlquote_from_bytes(path.as_posix().encode('utf-8')))
-
- def gethomedir(self, username):
- """Return the home directory of the current user."""
-
- # original version, not faked
- if 'HOME' in os.environ:
- userhome = os.environ['HOME']
- elif 'USERPROFILE' in os.environ:
- userhome = os.environ['USERPROFILE']
- elif 'HOMEPATH' in os.environ:
- try:
- drv = os.environ['HOMEDRIVE']
- except KeyError:
- drv = ''
- userhome = drv + os.environ['HOMEPATH']
- else:
- raise RuntimeError("Can't determine home directory")
-
- if username:
- # Try to guess user home directory. By default all users
- # directories are located in the same place and are named by
- # corresponding usernames. If current user home directory points
- # to nonstandard place, this guess is likely wrong.
- if os.environ['USERNAME'] != username:
- drv, root, parts = self.parse_parts((userhome,))
- if parts[-1] != os.environ['USERNAME']:
- raise RuntimeError("Can't determine home directory "
- "for %r" % username)
- parts[-1] = username
- if drv or root:
- userhome = drv + root + self.join(parts[1:])
- else:
- userhome = self.join(parts)
- return userhome
-
- def compile_pattern(self, pattern):
- return re.compile(fnmatch.translate(pattern), re.IGNORECASE).fullmatch
-
-
-class _FakePosixFlavour(_FakeFlavour):
- """Flavour used by PurePosixPath with some Unix specific implementations
- independent of FakeFilesystem properties.
- """
+ def gethomedir(self, username):
+ # original version, not faked
+ if not username:
+ try:
+ return os.environ["HOME"]
+ except KeyError:
+ import pwd
- def is_reserved(self, parts):
- return False
-
- def make_uri(self, path):
- # We represent the path using the local filesystem encoding,
- # for portability to other applications.
- bpath = bytes(path)
- return 'file://' + urlquote_from_bytes(bpath)
-
- def gethomedir(self, username):
- # original version, not faked
- if not username:
- try:
- return os.environ['HOME']
- except KeyError:
+ return pwd.getpwuid(os.getuid()).pw_dir
+ else:
import pwd
- return pwd.getpwuid(os.getuid()).pw_dir
- else:
- import pwd
- try:
- return pwd.getpwnam(username).pw_dir
- except KeyError:
- raise RuntimeError("Can't determine home directory "
- "for %r" % username)
- def compile_pattern(self, pattern):
- return re.compile(fnmatch.translate(pattern)).fullmatch
+ try:
+ return pwd.getpwnam(username).pw_dir
+ except KeyError:
+ raise RuntimeError(
+ "Can't determine home directory " "for %r" % username
+ )
+
+ def compile_pattern(self, pattern):
+ return re.compile(fnmatch.translate(pattern)).fullmatch
class FakePath(pathlib.Path):
@@ -479,42 +515,50 @@ class FakePath(pathlib.Path):
def __new__(cls, *args, **kwargs):
"""Creates the correct subclass based on OS."""
if cls is FakePathlibModule.Path:
- cls = (FakePathlibModule.WindowsPath
- if cls.filesystem.is_windows_fs
- else FakePathlibModule.PosixPath)
- self = cls._from_parts(args)
- return self
-
- @classmethod
- def _from_parts(cls, args, init=False): # pylint: disable=unused-argument
- # Overwritten to call _init to set the fake accessor,
- # which is not done since Python 3.10
- self = object.__new__(cls)
- self._init()
- drv, root, parts = self._parse_args(args)
- self._drv = drv
- self._root = root
- self._parts = parts
- return self
-
- @classmethod
- def _from_parsed_parts(cls, drv, root, parts):
- # Overwritten to call _init to set the fake accessor,
- # which is not done since Python 3.10
- self = object.__new__(cls)
- self._init()
- self._drv = drv
- self._root = root
- self._parts = parts
- return self
-
- def _init(self, template=None):
- """Initializer called from base class."""
- self._accessor = _fake_accessor
- self._closed = False
+ cls = (
+ FakePathlibModule.WindowsPath
+ if cls.filesystem.is_windows_fs
+ else FakePathlibModule.PosixPath
+ )
+ if sys.version_info < (3, 12):
+ return cls._from_parts(args) # pytype: disable=attribute-error
+ else:
+ return object.__new__(cls)
+
+ if sys.version_info[:2] == (3, 10):
+ # Overwritten class methods to call _init to set the fake accessor,
+ # which is not done in Python 3.10, and not needed from Python 3.11 on
+ @classmethod
+ def _from_parts(cls, args):
+ self = object.__new__(cls)
+ self._init()
+ drv, root, parts = self._parse_args(args) # pytype: disable=attribute-error
+ self._drv = drv
+ self._root = root
+ self._parts = parts
+ return self
+
+ @classmethod
+ def _from_parsed_parts(cls, drv, root, parts):
+ self = object.__new__(cls)
+ self._drv = drv
+ self._root = root
+ self._parts = parts
+ self._init()
+ return self
+
+ if sys.version_info < (3, 11):
+
+ def _init(self, template=None):
+ """Initializer called from base class."""
+ # only needed until Python 3.10
+ self._accessor = _fake_accessor
+ # only needed until Python 3.8
+ self._closed = False
def _path(self):
- """Returns the underlying path string as used by the fake filesystem.
+ """Returns the underlying path string as used by the fake
+ filesystem.
"""
return str(self)
@@ -525,48 +569,51 @@ class FakePath(pathlib.Path):
"""
return cls(cls.filesystem.cwd)
- def resolve(self, strict=None):
- """Make the path absolute, resolving all symlinks on the way and also
- normalizing it (for example turning slashes into backslashes
- under Windows).
+ if sys.version_info < (3, 12): # in 3.12, we can use the pathlib implementation
- Args:
- strict: If False (default) no exception is raised if the path
- does not exist.
- New in Python 3.6.
+ def resolve(self, strict=None):
+ """Make the path absolute, resolving all symlinks on the way and also
+ normalizing it (for example turning slashes into backslashes
+ under Windows).
- Raises:
- OSError: if the path doesn't exist (strict=True or Python < 3.6)
- """
- if sys.version_info >= (3, 6):
- if strict is None:
- strict = False
- else:
- if strict is not None:
- raise TypeError(
- "resolve() got an unexpected keyword argument 'strict'")
- strict = True
- if self._closed:
- self._raise_closed()
- path = self._flavour.resolve(self, strict=strict)
- if path is None:
- self.stat()
- path = str(self.absolute())
- path = self.filesystem.absnormpath(path)
- return FakePath(path)
-
- def open(self, mode='r', buffering=-1, encoding=None,
- errors=None, newline=None):
+ Args:
+ strict: If False (default) no exception is raised if the path
+ does not exist.
+ New in Python 3.6.
+
+ Raises:
+ OSError: if the path doesn't exist (strict=True or Python < 3.6)
+ """
+ if sys.version_info >= (3, 6):
+ if strict is None:
+ strict = False
+ else:
+ if strict is not None:
+ raise TypeError(
+ "resolve() got an unexpected keyword argument 'strict'"
+ )
+ strict = True
+ self._raise_on_closed()
+ path = self._flavour.resolve(
+ self, strict=strict
+ ) # pytype: disable=attribute-error
+ if path is None:
+ self.stat()
+ path = str(self.absolute())
+ path = self.filesystem.absnormpath(path)
+ return FakePath(path)
+
+ def open(self, mode="r", buffering=-1, encoding=None, errors=None, newline=None):
"""Open the file pointed by this path and return a fake file object.
Raises:
OSError: if the target object is a directory, the path is invalid
or permission is denied.
"""
- if self._closed:
- self._raise_closed()
+ self._raise_on_closed()
return FakeFileOpen(self.filesystem)(
- self._path(), mode, buffering, encoding, errors, newline)
+ self._path(), mode, buffering, encoding, errors, newline
+ )
def read_bytes(self):
"""Open the fake file in bytes mode, read it, and close the file.
@@ -575,16 +622,18 @@ class FakePath(pathlib.Path):
OSError: if the target object is a directory, the path is
invalid or permission is denied.
"""
- with FakeFileOpen(self.filesystem)(self._path(), mode='rb') as f:
+ with FakeFileOpen(self.filesystem)(
+ self._path(), mode="rb"
+ ) as f: # pytype: disable=attribute-error
return f.read()
def read_text(self, encoding=None, errors=None):
"""
Open the fake file in text mode, read it, and close the file.
"""
- with FakeFileOpen(self.filesystem)(self._path(), mode='r',
- encoding=encoding,
- errors=errors) as f:
+ with FakeFileOpen(self.filesystem)( # pytype: disable=attribute-error
+ self._path(), mode="r", encoding=encoding, errors=errors
+ ) as f:
return f.read()
def write_bytes(self, data):
@@ -597,7 +646,9 @@ class FakePath(pathlib.Path):
"""
# type-check for the buffer interface before truncating the file
view = memoryview(data)
- with FakeFileOpen(self.filesystem)(self._path(), mode='wb') as f:
+ with FakeFileOpen(self.filesystem)(
+ self._path(), mode="wb"
+ ) as f: # pytype: disable=attribute-error
return f.write(view)
def write_text(self, data, encoding=None, errors=None, newline=None):
@@ -617,16 +668,18 @@ class FakePath(pathlib.Path):
invalid or permission is denied.
"""
if not isinstance(data, str):
- raise TypeError('data must be str, not %s' %
- data.__class__.__name__)
+ raise TypeError("data must be str, not %s" % data.__class__.__name__)
if newline is not None and sys.version_info < (3, 10):
- raise TypeError("write_text() got an unexpected "
- "keyword argument 'newline'")
- with FakeFileOpen(self.filesystem)(self._path(),
- mode='w',
- encoding=encoding,
- errors=errors,
- newline=newline) as f:
+ raise TypeError(
+ "write_text() got an unexpected " "keyword argument 'newline'"
+ )
+ with FakeFileOpen(self.filesystem)( # pytype: disable=attribute-error
+ self._path(),
+ mode="w",
+ encoding=encoding,
+ errors=errors,
+ newline=newline,
+ ) as f:
return f.write(data)
@classmethod
@@ -635,13 +688,14 @@ class FakePath(pathlib.Path):
returned by os.path.expanduser('~')).
"""
home = os.path.expanduser("~")
- if cls.filesystem.is_windows_fs != (os.name == 'nt'):
+ if cls.filesystem.is_windows_fs != (os.name == "nt"):
username = os.path.split(home)[1]
if cls.filesystem.is_windows_fs:
- home = os.path.join('C:', 'Users', username)
+ home = os.path.join("C:", "Users", username)
else:
- home = os.path.join('home', username)
- cls.filesystem.create_dir(home)
+ home = os.path.join("home", username)
+ if not cls.filesystem.exists(home):
+ cls.filesystem.create_dir(home)
return cls(home.replace(os.sep, cls.filesystem.path_separator))
def samefile(self, other_path):
@@ -660,16 +714,21 @@ class FakePath(pathlib.Path):
other_st = other_path.stat()
except AttributeError:
other_st = self.filesystem.stat(other_path)
- return (st.st_ino == other_st.st_ino and
- st.st_dev == other_st.st_dev)
+ return st.st_ino == other_st.st_ino and st.st_dev == other_st.st_dev
def expanduser(self):
- """ Return a new path with expanded ~ and ~user constructs
+ """Return a new path with expanded ~ and ~user constructs
(as returned by os.path.expanduser)
"""
- return FakePath(os.path.expanduser(self._path())
- .replace(os.path.sep,
- self.filesystem.path_separator))
+ return FakePath(
+ os.path.expanduser(self._path()).replace(
+ os.path.sep, self.filesystem.path_separator
+ )
+ )
+
+ def _raise_on_closed(self):
+ if sys.version_info < (3, 9) and self._closed:
+ self._raise_closed()
def touch(self, mode=0o666, exist_ok=True):
"""Create a fake file for the path with the given access mode,
@@ -683,18 +742,36 @@ class FakePath(pathlib.Path):
Raises:
FileExistsError: if the file exists and exits_ok is False.
"""
- if self._closed:
- self._raise_closed()
+ self._raise_on_closed()
if self.exists():
if exist_ok:
self.filesystem.utime(self._path(), times=None)
else:
self.filesystem.raise_os_error(errno.EEXIST, self._path())
else:
- fake_file = self.open('w')
+ fake_file = self.open("w")
fake_file.close()
self.chmod(mode)
+ if sys.version_info >= (3, 12):
+ """These are reimplemented for now because the original implementation
+ checks the flavour against ntpath/posixpath.
+ """
+
+ def is_absolute(self):
+ if self.filesystem.is_windows_fs:
+ return self.drive and self.root
+ return os.path.isabs(self._path())
+
+ def is_reserved(self):
+ if not self.filesystem.is_windows_fs or not self._tail:
+ return False
+ if self._tail[0].startswith("\\\\"):
+ # UNC paths are never reserved.
+ return False
+ name = self._tail[-1].partition(".")[0].partition(":")[0].rstrip(" ")
+ return name.upper() in pathlib._WIN_RESERVED_NAMES
+
class FakePathlibModule:
"""Uses FakeFilesystem to provide a fake pathlib module replacement.
@@ -719,51 +796,54 @@ class FakePathlibModule:
class PurePosixPath(PurePath):
"""A subclass of PurePath, that represents non-Windows filesystem
paths"""
+
__slots__ = ()
class PureWindowsPath(PurePath):
"""A subclass of PurePath, that represents Windows filesystem paths"""
+
__slots__ = ()
class WindowsPath(FakePath, PureWindowsPath):
"""A subclass of Path and PureWindowsPath that represents
concrete Windows filesystem paths.
"""
+
__slots__ = ()
def owner(self):
- raise NotImplementedError(
- "Path.owner() is unsupported on this system")
+ raise NotImplementedError("Path.owner() is unsupported on this system")
def group(self):
- raise NotImplementedError(
- "Path.group() is unsupported on this system")
+ raise NotImplementedError("Path.group() is unsupported on this system")
def is_mount(self):
- raise NotImplementedError(
- "Path.is_mount() is unsupported on this system")
+ raise NotImplementedError("Path.is_mount() is unsupported on this system")
class PosixPath(FakePath, PurePosixPath):
"""A subclass of Path and PurePosixPath that represents
concrete non-Windows filesystem paths.
"""
+
__slots__ = ()
def owner(self):
- """Return the current user name. It is assumed that the fake
- file system was created by the current user.
+ """Return the username of the file owner.
+ It is assumed that `st_uid` is related to a real user,
+ otherwise `KeyError` is raised.
"""
import pwd
- return pwd.getpwuid(os.getuid()).pw_name
+ return pwd.getpwuid(self.stat().st_uid).pw_name
def group(self):
- """Return the current group name. It is assumed that the fake
- file system was created by the current user.
+ """Return the group name of the file group.
+ It is assumed that `st_gid` is related to a real group,
+ otherwise `KeyError` is raised.
"""
import grp
- return grp.getgrgid(os.getgid()).gr_name
+ return grp.getgrgid(self.stat().st_gid).gr_name
Path = FakePath
@@ -774,6 +854,7 @@ class FakePathlibModule:
class FakePathlibPathModule:
"""Patches `pathlib.Path` by passing all calls to FakePathlibModule."""
+
fake_pathlib = None
def __init__(self, filesystem=None):
@@ -786,6 +867,11 @@ class FakePathlibPathModule:
def __getattr__(self, name):
return getattr(self.fake_pathlib.Path, name)
+ @classmethod
+ def __instancecheck__(cls, instance):
+ # fake the inheritance to pass isinstance checks - see #666
+ return isinstance(instance, PurePath)
+
class RealPath(pathlib.Path):
"""Replacement for `pathlib.Path` if it shall not be faked.
@@ -793,13 +879,67 @@ class RealPath(pathlib.Path):
itself is not.
"""
+ if sys.version_info < (3, 12):
+ _flavour = (
+ pathlib._WindowsFlavour() # type:ignore
+ if os.name == "nt"
+ else pathlib._PosixFlavour() # type:ignore
+ ) # type:ignore
+ else:
+ _flavour = ntpath if os.name == "nt" else posixpath
+
def __new__(cls, *args, **kwargs):
"""Creates the correct subclass based on OS."""
if cls is RealPathlibModule.Path:
- cls = (RealPathlibModule.WindowsPath if os.name == 'nt'
- else RealPathlibModule.PosixPath)
- self = cls._from_parts(args)
- return self
+ cls = (
+ RealPathlibModule.WindowsPath # pytype: disable=attribute-error
+ if os.name == "nt"
+ else RealPathlibModule.PosixPath # pytype: disable=attribute-error
+ )
+ if sys.version_info < (3, 12):
+ return cls._from_parts(args) # pytype: disable=attribute-error
+ else:
+ return object.__new__(cls)
+
+
+if sys.version_info > (3, 10):
+
+ def with_original_os(f: Callable) -> Callable:
+ """Decorator used for real pathlib Path methods to ensure that
+ real os functions instead of faked ones are used."""
+
+ @functools.wraps(f)
+ def wrapped(*args, **kwargs):
+ with use_original_os():
+ return f(*args, **kwargs)
+
+ return wrapped
+
+ for name, fn in inspect.getmembers(RealPath, inspect.isfunction):
+ if not name.startswith("__"):
+ setattr(RealPath, name, with_original_os(fn))
+
+
+class RealPathlibPathModule:
+ """Patches `pathlib.Path` by passing all calls to RealPathlibModule."""
+
+ real_pathlib = None
+
+ @classmethod
+ def __instancecheck__(cls, instance):
+ # as we cannot derive from pathlib.Path, we fake
+ # the inheritance to pass isinstance checks - see #666
+ return isinstance(instance, PurePath)
+
+ def __init__(self):
+ if self.real_pathlib is None:
+ self.__class__.real_pathlib = RealPathlibModule()
+
+ def __call__(self, *args, **kwargs):
+ return RealPath(*args, **kwargs)
+
+ def __getattr__(self, name):
+ return getattr(self.real_pathlib.Path, name)
class RealPathlibModule:
@@ -809,29 +949,34 @@ class RealPathlibModule:
"""
def __init__(self):
- RealPathlibModule.PureWindowsPath._flavour = pathlib._WindowsFlavour()
- RealPathlibModule.PurePosixPath._flavour = pathlib._PosixFlavour()
self._pathlib_module = pathlib
class PurePosixPath(PurePath):
"""A subclass of PurePath, that represents Posix filesystem paths"""
+
__slots__ = ()
class PureWindowsPath(PurePath):
"""A subclass of PurePath, that represents Windows filesystem paths"""
+
__slots__ = ()
- if sys.platform == 'win32':
+ if sys.platform == "win32":
+
class WindowsPath(RealPath, PureWindowsPath):
"""A subclass of Path and PureWindowsPath that represents
concrete Windows filesystem paths.
"""
+
__slots__ = ()
+
else:
+
class PosixPath(RealPath, PurePosixPath):
"""A subclass of Path and PurePosixPath that represents
concrete non-Windows filesystem paths.
"""
+
__slots__ = ()
Path = RealPath
@@ -839,24 +984,3 @@ class RealPathlibModule:
def __getattr__(self, name):
"""Forwards any unfaked calls to the standard pathlib module."""
return getattr(self._pathlib_module, name)
-
-
-class RealPathlibPathModule:
- """Patches `pathlib.Path` by passing all calls to RealPathlibModule."""
- real_pathlib = None
-
- @classmethod
- def __instancecheck__(cls, instance):
- # as we cannot derive from pathlib.Path, we fake
- # the inheritance to pass isinstance checks - see #666
- return isinstance(instance, PurePath)
-
- def __init__(self):
- if self.real_pathlib is None:
- self.__class__.real_pathlib = RealPathlibModule()
-
- def __call__(self, *args, **kwargs):
- return self.real_pathlib.Path(*args, **kwargs)
-
- def __getattr__(self, name):
- return getattr(self.real_pathlib.Path, name)
diff --git a/pyfakefs/fake_scandir.py b/pyfakefs/fake_scandir.py
index 8941973..cfe9f2f 100644
--- a/pyfakefs/fake_scandir.py
+++ b/pyfakefs/fake_scandir.py
@@ -20,7 +20,7 @@ import os
import sys
from pyfakefs.extra_packages import use_scandir_package
-from pyfakefs.helpers import to_string
+from pyfakefs.helpers import to_string, make_string_path
if sys.version_info >= (3, 6):
BaseClass = os.PathLike
@@ -39,9 +39,9 @@ class DirEntry(BaseClass):
filesystem: the fake filesystem used for implementation.
"""
self._filesystem = filesystem
- self.name = ''
- self.path = ''
- self._abspath = ''
+ self.name = ""
+ self.path = ""
+ self._abspath = ""
self._inode = None
self._islink = False
self._isdir = False
@@ -110,9 +110,20 @@ class DirEntry(BaseClass):
return self._statresult
if sys.version_info >= (3, 6):
+
def __fspath__(self):
return self.path
+ if sys.version_info >= (3, 12):
+
+ def is_junction(self) -> bool:
+ """Return True if this entry is a junction.
+ Junctions are not a part of posix semantic."""
+ if not self._filesystem.is_windows_fs:
+ return False
+ file_object = self._filesystem.resolve(self._abspath)
+ return file_object.is_junction
+
class ScanDirIter:
"""Iterator for DirEntry objects returned from `scandir()`
@@ -122,15 +133,17 @@ class ScanDirIter:
self.filesystem = filesystem
if isinstance(path, int):
if not use_scandir_package and (
- sys.version_info < (3, 7) or
- self.filesystem.is_windows_fs):
+ sys.version_info < (3, 7) or self.filesystem.is_windows_fs
+ ):
raise NotImplementedError(
- 'scandir does not support file descriptor '
- 'path argument')
+ "scandir does not support file descriptor " "path argument"
+ )
self.abspath = self.filesystem.absnormpath(
- self.filesystem.get_open_file(path).get_object().path)
- self.path = ''
+ self.filesystem.get_open_file(path).get_object().path
+ )
+ self.path = ""
else:
+ path = make_string_path(path)
self.abspath = self.filesystem.absnormpath(path)
self.path = to_string(path)
entries = self.filesystem.confirmdir(self.abspath).entries
@@ -143,15 +156,14 @@ class ScanDirIter:
entry = self.entry_iter.__next__()
dir_entry = DirEntry(self.filesystem)
dir_entry.name = entry
- dir_entry.path = self.filesystem.joinpaths(self.path,
- dir_entry.name)
- dir_entry._abspath = self.filesystem.joinpaths(self.abspath,
- dir_entry.name)
+ dir_entry.path = self.filesystem.joinpaths(self.path, dir_entry.name)
+ dir_entry._abspath = self.filesystem.joinpaths(self.abspath, dir_entry.name)
dir_entry._isdir = self.filesystem.isdir(dir_entry._abspath)
dir_entry._islink = self.filesystem.islink(dir_entry._abspath)
return dir_entry
if sys.version_info >= (3, 6):
+
def __enter__(self):
return self
@@ -162,7 +174,7 @@ class ScanDirIter:
pass
-def scandir(filesystem, path=''):
+def scandir(filesystem, path=""):
"""Return an iterator of DirEntry objects corresponding to the entries
in the directory given by path.
@@ -269,12 +281,12 @@ class FakeScanDirModule:
"""Return the list of patched function names. Used for patching
functions imported from the module.
"""
- return 'scandir', 'walk'
+ return "scandir", "walk"
def __init__(self, filesystem):
self.filesystem = filesystem
- def scandir(self, path='.'):
+ def scandir(self, path="."):
"""Return an iterator of DirEntry objects corresponding to the entries
in the directory given by path.
diff --git a/pyfakefs/helpers.py b/pyfakefs/helpers.py
index ba75d2a..5d5d590 100644
--- a/pyfakefs/helpers.py
+++ b/pyfakefs/helpers.py
@@ -22,12 +22,75 @@ from copy import copy
from stat import S_IFLNK
from typing import Union, Optional, Any, AnyStr, overload, cast
-IS_PYPY = platform.python_implementation() == 'PyPy'
-IS_WIN = sys.platform == 'win32'
-IN_DOCKER = os.path.exists('/.dockerenv')
-
+AnyString = Union[str, bytes]
AnyPath = Union[AnyStr, os.PathLike]
+IS_PYPY = platform.python_implementation() == "PyPy"
+IS_WIN = sys.platform == "win32"
+IN_DOCKER = os.path.exists("/.dockerenv")
+
+PERM_READ = 0o400 # Read permission bit.
+PERM_WRITE = 0o200 # Write permission bit.
+PERM_EXE = 0o100 # Execute permission bit.
+PERM_DEF = 0o777 # Default permission bits.
+PERM_DEF_FILE = 0o666 # Default permission bits (regular file)
+PERM_ALL = 0o7777 # All permission bits.
+
+if sys.platform == "win32":
+ USER_ID = 1
+ GROUP_ID = 1
+else:
+ USER_ID = os.getuid()
+ GROUP_ID = os.getgid()
+
+
+def get_uid() -> int:
+ """Get the global user id. Same as ``os.getuid()``"""
+ return USER_ID
+
+
+def set_uid(uid: int) -> None:
+ """Set the global user id. This is used as st_uid for new files
+ and to differentiate between a normal user and the root user (uid 0).
+ For the root user, some permission restrictions are ignored.
+
+ Args:
+ uid: (int) the user ID of the user calling the file system functions.
+ """
+ global USER_ID
+ USER_ID = uid
+
+
+def get_gid() -> int:
+ """Get the global group id. Same as ``os.getgid()``"""
+ return GROUP_ID
+
+
+def set_gid(gid: int) -> None:
+ """Set the global group id. This is only used to set st_gid for new files,
+ no permission checks are performed.
+
+ Args:
+ gid: (int) the group ID of the user calling the file system functions.
+ """
+ global GROUP_ID
+ GROUP_ID = gid
+
+
+def reset_ids() -> None:
+ """Set the global user ID and group ID back to default values."""
+ if sys.platform == "win32":
+ set_uid(1)
+ set_gid(1)
+ else:
+ set_uid(os.getuid())
+ set_gid(os.getgid())
+
+
+def is_root() -> bool:
+ """Return True if the current user is the root user."""
+ return USER_ID == 0
+
def is_int_type(val: Any) -> bool:
"""Return True if `val` is of integer type."""
@@ -37,30 +100,32 @@ def is_int_type(val: Any) -> bool:
def is_byte_string(val: Any) -> bool:
"""Return True if `val` is a bytes-like object, False for a unicode
string."""
- return not hasattr(val, 'encode')
+ return not hasattr(val, "encode")
def is_unicode_string(val: Any) -> bool:
"""Return True if `val` is a unicode string, False for a bytes-like
object."""
- return hasattr(val, 'encode')
+ return hasattr(val, "encode")
@overload
-def make_string_path(dir_name: AnyStr) -> AnyStr: ...
+def make_string_path(dir_name: AnyStr) -> AnyStr:
+ ...
@overload
-def make_string_path(dir_name: os.PathLike) -> str: ...
+def make_string_path(dir_name: os.PathLike) -> str:
+ ...
def make_string_path(dir_name: AnyPath) -> AnyStr:
- return cast(AnyStr, os.fspath(dir_name))
+ return cast(AnyStr, os.fspath(dir_name)) # pytype: disable=invalid-annotation
def to_string(path: Union[AnyStr, Union[str, bytes]]) -> str:
"""Return the string representation of a byte string using the preferred
- encoding, or the string itself if path is a str."""
+ encoding, or the string itself if path is a str."""
if isinstance(path, bytes):
return path.decode(locale.getpreferredencoding(False))
return path
@@ -68,7 +133,7 @@ def to_string(path: Union[AnyStr, Union[str, bytes]]) -> str:
def to_bytes(path: Union[AnyStr, Union[str, bytes]]) -> bytes:
"""Return the bytes representation of a string using the preferred
- encoding, or the byte string itself if path is a byte string."""
+ encoding, or the byte string itself if path is a byte string."""
if isinstance(path, str):
return bytes(path, locale.getpreferredencoding(False))
return path
@@ -93,19 +158,23 @@ def now():
@overload
-def matching_string(matched: bytes, string: AnyStr) -> bytes: ...
+def matching_string(matched: bytes, string: AnyStr) -> bytes:
+ ...
@overload
-def matching_string(matched: str, string: AnyStr) -> str: ...
+def matching_string(matched: str, string: AnyStr) -> str:
+ ...
@overload
-def matching_string(matched: AnyStr, string: None) -> None: ...
+def matching_string(matched: AnyStr, string: None) -> None:
+ ...
def matching_string( # type: ignore[misc]
- matched: AnyStr, string: Optional[AnyStr]) -> Optional[AnyStr]:
+ matched: AnyStr, string: Optional[AnyStr]
+) -> Optional[AnyString]:
"""Return the string as byte or unicode depending
on the type of matched, assuming string is an ASCII string.
"""
@@ -113,7 +182,7 @@ def matching_string( # type: ignore[misc]
return string
if isinstance(matched, bytes) and isinstance(string, str):
return string.encode(locale.getpreferredencoding(False))
- return string
+ return string # pytype: disable=bad-return-type
class FakeStatResult:
@@ -121,11 +190,14 @@ class FakeStatResult:
This is needed as `os.stat_result` has no possibility to set
nanosecond times directly.
"""
- _stat_float_times: bool = True
- def __init__(self, is_windows: bool, user_id: int, group_id: int,
- initial_time: Optional[float] = None):
- self._use_float: Optional[bool] = None
+ def __init__(
+ self,
+ is_windows: bool,
+ user_id: int,
+ group_id: int,
+ initial_time: Optional[float] = None,
+ ):
self.st_mode: int = 0
self.st_ino: Optional[int] = None
self.st_dev: int = 0
@@ -138,29 +210,19 @@ class FakeStatResult:
self._st_mtime_ns: int = self._st_atime_ns
self._st_ctime_ns: int = self._st_atime_ns
- @property
- def use_float(self) -> bool:
- if self._use_float is None:
- return self.stat_float_times()
- return self._use_float
-
- @use_float.setter
- def use_float(self, val: bool) -> None:
- self._use_float = val
-
def __eq__(self, other: Any) -> bool:
return (
- isinstance(other, FakeStatResult) and
- self._st_atime_ns == other._st_atime_ns and
- self._st_ctime_ns == other._st_ctime_ns and
- self._st_mtime_ns == other._st_mtime_ns and
- self.st_size == other.st_size and
- self.st_gid == other.st_gid and
- self.st_uid == other.st_uid and
- self.st_nlink == other.st_nlink and
- self.st_dev == other.st_dev and
- self.st_ino == other.st_ino and
- self.st_mode == other.st_mode
+ isinstance(other, FakeStatResult)
+ and self._st_atime_ns == other._st_atime_ns
+ and self._st_ctime_ns == other._st_ctime_ns
+ and self._st_mtime_ns == other._st_mtime_ns
+ and self.st_size == other.st_size
+ and self.st_gid == other.st_gid
+ and self.st_uid == other.st_uid
+ and self.st_nlink == other.st_nlink
+ and self.st_dev == other.st_dev
+ and self.st_ino == other.st_ino
+ and self.st_mode == other.st_mode
)
def __ne__(self, other: Any) -> bool:
@@ -171,7 +233,6 @@ class FakeStatResult:
behavior of the real os.stat_result.
"""
stat_result = copy(self)
- stat_result.use_float = self.use_float
return stat_result
def set_from_stat_result(self, stat_result: os.stat_result) -> None:
@@ -187,27 +248,10 @@ class FakeStatResult:
self._st_mtime_ns = stat_result.st_mtime_ns
self._st_ctime_ns = stat_result.st_ctime_ns
- @classmethod
- def stat_float_times(cls, newvalue: Optional[bool] = None) -> bool:
- """Determine whether a file's time stamps are reported as floats
- or ints.
-
- Calling without arguments returns the current value.
- The value is shared by all instances of FakeOsModule.
-
- Args:
- newvalue: If `True`, mtime, ctime, atime are reported as floats.
- Otherwise, they are returned as ints (rounding down).
- """
- if newvalue is not None:
- cls._stat_float_times = bool(newvalue)
- return cls._stat_float_times
-
@property
def st_ctime(self) -> Union[int, float]:
"""Return the creation time in seconds."""
- ctime = self._st_ctime_ns / 1e9
- return ctime if self.use_float else int(ctime)
+ return self._st_ctime_ns / 1e9
@st_ctime.setter
def st_ctime(self, val: Union[int, float]) -> None:
@@ -217,8 +261,7 @@ class FakeStatResult:
@property
def st_atime(self) -> Union[int, float]:
"""Return the access time in seconds."""
- atime = self._st_atime_ns / 1e9
- return atime if self.use_float else int(atime)
+ return self._st_atime_ns / 1e9
@st_atime.setter
def st_atime(self, val: Union[int, float]) -> None:
@@ -228,8 +271,7 @@ class FakeStatResult:
@property
def st_mtime(self) -> Union[int, float]:
"""Return the modification time in seconds."""
- mtime = self._st_mtime_ns / 1e9
- return mtime if self.use_float else int(mtime)
+ return self._st_mtime_ns / 1e9
@st_mtime.setter
def st_mtime(self, val: Union[int, float]) -> None:
@@ -247,27 +289,45 @@ class FakeStatResult:
self._st_size = val
@property
+ def st_blocks(self) -> int:
+ """Return the number of 512-byte blocks allocated for the file.
+ Assumes a page size of 4096 (matches most systems).
+ Ignores that this may not be available under some systems,
+ and that the result may differ if the file has holes.
+ """
+ if self.is_windows:
+ raise AttributeError("'os.stat_result' object has no attribute 'st_blocks'")
+ page_size = 4096
+ blocks_in_page = page_size // 512
+ pages = self._st_size // page_size
+ if self._st_size % page_size:
+ pages += 1
+ return pages * blocks_in_page
+
+ @property
def st_file_attributes(self) -> int:
if not self.is_windows:
- raise AttributeError("module 'os.stat_result' "
- "has no attribute 'st_file_attributes'")
+ raise AttributeError(
+ "module 'os.stat_result' " "has no attribute 'st_file_attributes'"
+ )
mode = 0
st_mode = self.st_mode
if st_mode & stat.S_IFDIR:
- mode |= stat.FILE_ATTRIBUTE_DIRECTORY
+ mode |= stat.FILE_ATTRIBUTE_DIRECTORY # type:ignore[attr-defined]
if st_mode & stat.S_IFREG:
- mode |= stat.FILE_ATTRIBUTE_NORMAL
+ mode |= stat.FILE_ATTRIBUTE_NORMAL # type:ignore[attr-defined]
if st_mode & (stat.S_IFCHR | stat.S_IFBLK):
- mode |= stat.FILE_ATTRIBUTE_DEVICE
+ mode |= stat.FILE_ATTRIBUTE_DEVICE # type:ignore[attr-defined]
if st_mode & stat.S_IFLNK:
- mode |= stat.FILE_ATTRIBUTE_REPARSE_POINT
+ mode |= stat.FILE_ATTRIBUTE_REPARSE_POINT # type:ignore
return mode
@property
def st_reparse_tag(self) -> int:
if not self.is_windows or sys.version_info < (3, 8):
- raise AttributeError("module 'os.stat_result' "
- "has no attribute 'st_reparse_tag'")
+ raise AttributeError(
+ "module 'os.stat_result' " "has no attribute 'st_reparse_tag'"
+ )
if self.st_mode & stat.S_IFLNK:
return stat.IO_REPARSE_TAG_SYMLINK # type: ignore[attr-defined]
return 0
@@ -297,7 +357,7 @@ class FakeStatResult:
return int(self.st_mtime)
if item == stat.ST_CTIME:
return int(self.st_ctime)
- raise ValueError('Invalid item')
+ raise ValueError("Invalid item")
@property
def st_atime_ns(self) -> int:
@@ -334,21 +394,23 @@ class BinaryBufferIO(io.BytesIO):
"""Stream class that handles byte contents for files."""
def __init__(self, contents: Optional[bytes]):
- super().__init__(contents or b'')
+ super().__init__(contents or b"")
def putvalue(self, value: bytes) -> None:
self.write(value)
class TextBufferIO(io.TextIOWrapper):
- """Stream class that handles Python string contents for files.
- """
-
- def __init__(self, contents: Optional[bytes] = None,
- newline: Optional[str] = None,
- encoding: Optional[str] = None,
- errors: str = 'strict'):
- self._bytestream = io.BytesIO(contents or b'')
+ """Stream class that handles Python string contents for files."""
+
+ def __init__(
+ self,
+ contents: Optional[bytes] = None,
+ newline: Optional[str] = None,
+ encoding: Optional[str] = None,
+ errors: str = "strict",
+ ):
+ self._bytestream = io.BytesIO(contents or b"")
super().__init__(self._bytestream, encoding, errors, newline)
def getvalue(self) -> bytes:
diff --git a/pyfakefs/mox3_stubout.py b/pyfakefs/mox3_stubout.py
index d936dcd..c3f3a88 100644
--- a/pyfakefs/mox3_stubout.py
+++ b/pyfakefs/mox3_stubout.py
@@ -30,16 +30,16 @@ import inspect
class StubOutForTesting:
"""Sample Usage:
- You want os.path.exists() to always return true during testing.
+ You want os.path.exists() to always return true during testing.
- stubs = StubOutForTesting()
- stubs.Set(os.path, 'exists', lambda x: 1)
- ...
- stubs.UnsetAll()
+ stubs = StubOutForTesting()
+ stubs.Set(os.path, 'exists', lambda x: 1)
+ ...
+ stubs.UnsetAll()
- The above changes os.path.exists into a lambda that returns 1. Once
- the ... part of the code finishes, the UnsetAll() looks up the old value
- of os.path.exists and restores it.
+ The above changes os.path.exists into a lambda that returns 1. Once
+ the ... part of the code finishes, the UnsetAll() looks up the old value
+ of os.path.exists and restores it.
"""
@@ -72,8 +72,9 @@ class StubOutForTesting:
Raises AttributeError if the attribute cannot be found.
"""
- if (inspect.ismodule(obj) or
- (not inspect.isclass(obj) and attr_name in obj.__dict__)):
+ if inspect.ismodule(obj) or (
+ not inspect.isclass(obj) and attr_name in obj.__dict__
+ ):
orig_obj = obj
orig_attr = getattr(obj, attr_name)
@@ -100,9 +101,8 @@ class StubOutForTesting:
# Calling getattr() on a staticmethod transforms it to a 'normal'
# function. We need to ensure that we put it back as a staticmethod.
old_attribute = obj.__dict__.get(attr_name)
- if (old_attribute is not None
- and isinstance(old_attribute, staticmethod)):
- orig_attr = staticmethod(orig_attr)
+ if old_attribute is not None and isinstance(old_attribute, staticmethod):
+ orig_attr = staticmethod(orig_attr) # pytype: disable=not-callable
self.stubs.append((orig_obj, attr_name, orig_attr))
setattr(orig_obj, attr_name, new_attr)
@@ -157,6 +157,6 @@ class StubOutForTesting:
# undone)
self.cache.reverse()
- for (parent, old_child, child_name) in self.cache:
+ for parent, old_child, child_name in self.cache:
setattr(parent, child_name, old_child)
self.cache = []
diff --git a/pyfakefs/patched_packages.py b/pyfakefs/patched_packages.py
index 749b795..0d7651c 100644
--- a/pyfakefs/patched_packages.py
+++ b/pyfakefs/patched_packages.py
@@ -17,6 +17,7 @@ with pyfakefs.
import sys
try:
+ import pandas as pd
import pandas.io.parsers as parsers
except ImportError:
parsers = None
@@ -31,35 +32,40 @@ try:
except ImportError:
locks = None
+# From pandas v 1.2 onwards the python fs functions are used even when the engine
+# selected is "c". This means that we don't explicitly have to change the engine.
+patch_pandas = parsers is not None and [int(v) for v in pd.__version__.split(".")] < [
+ 1,
+ 2,
+ 0,
+]
+
def get_modules_to_patch():
modules_to_patch = {}
if xlrd is not None:
- modules_to_patch['xlrd'] = XLRDModule
+ modules_to_patch["xlrd"] = XLRDModule
if locks is not None:
- modules_to_patch['django.core.files.locks'] = FakeLocks
+ modules_to_patch["django.core.files.locks"] = FakeLocks
return modules_to_patch
def get_classes_to_patch():
classes_to_patch = {}
- if parsers is not None:
- classes_to_patch[
- 'TextFileReader'
- ] = 'pandas.io.parsers'
+ if patch_pandas:
+ classes_to_patch["TextFileReader"] = ["pandas.io.parsers"]
return classes_to_patch
def get_fake_module_classes():
fake_module_classes = {}
- if parsers is not None:
- fake_module_classes[
- 'TextFileReader'
- ] = FakeTextFileReader
+ if patch_pandas:
+ fake_module_classes["TextFileReader"] = FakeTextFileReader
return fake_module_classes
if xlrd is not None:
+
class XLRDModule:
"""Patches the xlrd module, which is used as the default Excel file
reader by pandas. Disables using memory mapped files, which are
@@ -68,24 +74,36 @@ if xlrd is not None:
def __init__(self, _):
self._xlrd_module = xlrd
- def open_workbook(self, filename=None,
- logfile=sys.stdout,
- verbosity=0,
- use_mmap=False,
- file_contents=None,
- encoding_override=None,
- formatting_info=False,
- on_demand=False,
- ragged_rows=False):
+ def open_workbook(
+ self,
+ filename=None,
+ logfile=sys.stdout,
+ verbosity=0,
+ use_mmap=False,
+ file_contents=None,
+ encoding_override=None,
+ formatting_info=False,
+ on_demand=False,
+ ragged_rows=False,
+ ):
return self._xlrd_module.open_workbook(
- filename, logfile, verbosity, False, file_contents,
- encoding_override, formatting_info, on_demand, ragged_rows)
+ filename,
+ logfile,
+ verbosity,
+ False,
+ file_contents,
+ encoding_override,
+ formatting_info,
+ on_demand,
+ ragged_rows,
+ )
def __getattr__(self, name):
"""Forwards any unfaked calls to the standard xlrd module."""
return getattr(self._xlrd_module, name)
-if parsers is not None:
+
+if patch_pandas:
# we currently need to add fake modules for both the parser module and
# the contained text reader - maybe this can be simplified
@@ -108,16 +126,19 @@ if parsers is not None:
class TextFileReader(parsers.TextFileReader):
def __init__(self, *args, **kwargs):
- kwargs['engine'] = 'python'
+ kwargs["engine"] = "python"
super().__init__(*args, **kwargs)
def __getattr__(self, name):
"""Forwards any unfaked calls to the standard xlrd module."""
return getattr(self._parsers_module, name)
+
if locks is not None:
+
class FakeLocks:
"""django.core.files.locks uses low level OS functions, fake it."""
+
_locks_module = locks
def __init__(self, _):
diff --git a/pyfakefs/py.typed b/pyfakefs/py.typed
new file mode 100644
index 0000000..d149b18
--- /dev/null
+++ b/pyfakefs/py.typed
@@ -0,0 +1 @@
+# Marker file for PEP 561. The pyfakefs package uses inline types.
diff --git a/pyfakefs/pytest_plugin.py b/pyfakefs/pytest_plugin.py
index 3d3306c..37b055f 100644
--- a/pyfakefs/pytest_plugin.py
+++ b/pyfakefs/pytest_plugin.py
@@ -8,22 +8,29 @@ def my_fakefs_test(fs):
fs.create_file('/var/data/xx1.txt')
assert os.path.exists('/var/data/xx1.txt')
"""
-import _pytest
+
import py
import pytest
+from _pytest import capture
from pyfakefs.fake_filesystem_unittest import Patcher
+try:
+ from _pytest import pathlib
+except ImportError:
+ pathlib = None # type:ignore[assignment]
+
Patcher.SKIPMODULES.add(py)
Patcher.SKIPMODULES.add(pytest)
-if hasattr(_pytest, "pathlib"):
- Patcher.SKIPMODULES.add(_pytest.pathlib)
+Patcher.SKIPMODULES.add(capture)
+if pathlib is not None:
+ Patcher.SKIPMODULES.add(pathlib)
@pytest.fixture
def fs(request):
- """ Fake filesystem. """
- if hasattr(request, 'param'):
+ """Fake filesystem."""
+ if hasattr(request, "param"):
# pass optional parameters via @pytest.mark.parametrize
patcher = Patcher(*request.param)
else:
@@ -31,3 +38,45 @@ def fs(request):
patcher.setUp()
yield patcher.fs
patcher.tearDown()
+
+
+@pytest.fixture(scope="class")
+def fs_class(request):
+ """Class-scoped fake filesystem fixture."""
+ if hasattr(request, "param"):
+ patcher = Patcher(*request.param)
+ else:
+ patcher = Patcher()
+ patcher.setUp()
+ yield patcher.fs
+ patcher.tearDown()
+
+
+@pytest.fixture(scope="module")
+def fs_module(request):
+ """Module-scoped fake filesystem fixture."""
+ if hasattr(request, "param"):
+ patcher = Patcher(*request.param)
+ else:
+ patcher = Patcher()
+ patcher.setUp()
+ yield patcher.fs
+ patcher.tearDown()
+
+
+@pytest.fixture(scope="session")
+def fs_session(request):
+ """Session-scoped fake filesystem fixture."""
+ if hasattr(request, "param"):
+ patcher = Patcher(*request.param)
+ else:
+ patcher = Patcher()
+ patcher.setUp()
+ yield patcher.fs
+ patcher.tearDown()
+
+
+@pytest.hookimpl(tryfirst=True)
+def pytest_sessionfinish(session, exitstatus):
+ """Make sure that the cache is cleared before the final test shutdown."""
+ Patcher.clear_fs_cache()
diff --git a/pyfakefs/pytest_tests/conftest.py b/pyfakefs/pytest_tests/conftest.py
index b6918c7..d23dad2 100644
--- a/pyfakefs/pytest_tests/conftest.py
+++ b/pyfakefs/pytest_tests/conftest.py
@@ -20,14 +20,14 @@ import pytest
from pyfakefs.fake_filesystem_unittest import Patcher
# import the fs fixture to be visible if pyfakefs is not installed
-from pyfakefs.pytest_plugin import fs # noqa: F401
+from pyfakefs.pytest_plugin import fs, fs_module # noqa: F401
from pyfakefs.pytest_tests import example # noqa: E402
@pytest.fixture
def fs_reload_example():
- """ Fake filesystem. """
+ """Fake filesystem."""
patcher = Patcher(modules_to_reload=[example])
patcher.setUp()
yield patcher.fs
diff --git a/pyfakefs/pytest_tests/example.py b/pyfakefs/pytest_tests/example.py
index c5b530b..c9eb43e 100644
--- a/pyfakefs/pytest_tests/example.py
+++ b/pyfakefs/pytest_tests/example.py
@@ -14,4 +14,4 @@
from pathlib import Path
-EXAMPLE_FILE = Path('/test') / 'file'
+EXAMPLE_FILE = Path("/test") / "file"
diff --git a/pyfakefs/pytest_tests/io.py b/pyfakefs/pytest_tests/io.py
new file mode 100644
index 0000000..e6ea4bf
--- /dev/null
+++ b/pyfakefs/pytest_tests/io.py
@@ -0,0 +1,14 @@
+"""
+This is a test case for pyfakefs issue #708.
+It tests the usage of an own module with the same name as a patched filesystem
+module, the content is taken from the issue.
+"""
+
+
+class InputStream:
+ def __init__(self, name):
+ self.name = name
+
+ def read(self):
+ with open(self.name, "r") as f:
+ return f.readline()
diff --git a/pyfakefs/pytest_tests/ns_package/test/ns_package/test/test_file.py b/pyfakefs/pytest_tests/ns_package/test/ns_package/test/test_file.py
new file mode 100644
index 0000000..c73b8d6
--- /dev/null
+++ b/pyfakefs/pytest_tests/ns_package/test/ns_package/test/test_file.py
@@ -0,0 +1,7 @@
+import pyfakefs.fake_filesystem
+
+
+def test_foo(fs):
+ """Regression test for #814 - must run in namespace package with cli logging."""
+ fs.os = pyfakefs.fake_filesystem.OSType.WINDOWS
+ assert True
diff --git a/pyfakefs/pytest_tests/ns_package/test/setup.py b/pyfakefs/pytest_tests/ns_package/test/setup.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/pyfakefs/pytest_tests/ns_package/test/setup.py
diff --git a/pyfakefs/pytest_tests/pytest_check_failed_plugin_test.py b/pyfakefs/pytest_tests/pytest_check_failed_plugin_test.py
index 42ff87e..2725cde 100644
--- a/pyfakefs/pytest_tests/pytest_check_failed_plugin_test.py
+++ b/pyfakefs/pytest_tests/pytest_check_failed_plugin_test.py
@@ -7,15 +7,14 @@ import os
import pytest
-@pytest.mark.skipif(not os.path.exists('testresult.txt'),
- reason='Only run in CI tests')
+@pytest.mark.skipif(not os.path.exists("testresult.txt"), reason="Only run in CI tests")
def test_failed_testresult_stacktrace():
- with open('testresult.txt') as f:
+ with open("testresult.txt") as f:
contents = f.read()
# before the fix, a triple question mark has been displayed
# instead of the stacktrace
assert contents
- print('contents', contents)
- assert '???' not in contents
- assert 'AttributeError' not in contents
- assert 'def test_fs(fs):' in contents
+ print("contents", contents)
+ assert "???" not in contents
+ assert "AttributeError" not in contents
+ assert "def test_fs(fs):" in contents
diff --git a/pyfakefs/pytest_tests/pytest_doctest_test.py b/pyfakefs/pytest_tests/pytest_doctest_test.py
index 4a36788..9bb9c54 100644
--- a/pyfakefs/pytest_tests/pytest_doctest_test.py
+++ b/pyfakefs/pytest_tests/pytest_doctest_test.py
@@ -12,10 +12,10 @@ from __future__ import unicode_literals
def make_file_factory(func_name, fake, result):
- """ Return a simple function with parametrized doctest. """
+ """Return a simple function with parametrized doctest."""
- def make_file(name, content=''):
- with open(name, 'w') as f:
+ def make_file(name, content=""):
+ with open(name, "w") as f:
f.write(content)
make_file.__doc__ = """
@@ -29,20 +29,20 @@ def make_file_factory(func_name, fake, result):
""".format(
command="getfixture('fs')" if fake else "pass",
func_name=func_name,
- result=result)
+ result=result,
+ )
return make_file
-passes = make_file_factory('passes', fake=False, result=True)
-passes_too = make_file_factory('passes_too', fake=True, result=True)
+passes = make_file_factory("passes", fake=False, result=True)
+passes_too = make_file_factory("passes_too", fake=True, result=True)
-passes_too.__doc__ = passes_too.__doc__.replace('>>> os.remove(name)',
- '>>> pass')
+passes_too.__doc__ = passes_too.__doc__.replace(">>> os.remove(name)", ">>> pass")
-fails = make_file_factory('fails', fake=False, result=False)
+fails = make_file_factory("fails", fake=False, result=False)
# Pytest versions below 2.8.6 raise an internal error when running
# these doctests:
-crashes = make_file_factory('crashes', fake=True, result=False)
-crashes_too = make_file_factory(') SyntaxError', fake=True, result=False)
+crashes = make_file_factory("crashes", fake=True, result=False)
+crashes_too = make_file_factory(") SyntaxError", fake=True, result=False)
diff --git a/pyfakefs/pytest_tests/pytest_fixture_param_test.py b/pyfakefs/pytest_tests/pytest_fixture_param_test.py
index aa6a44d..e1c766f 100644
--- a/pyfakefs/pytest_tests/pytest_fixture_param_test.py
+++ b/pyfakefs/pytest_tests/pytest_fixture_param_test.py
@@ -23,24 +23,24 @@ import pyfakefs.pytest_tests.example as example
def test_example_file_failing(fs):
"""Test fails because EXAMPLE_FILE is cached in the module
and not patched."""
- fs.create_file(example.EXAMPLE_FILE, contents='stuff here')
+ fs.create_file(example.EXAMPLE_FILE, contents="stuff here")
check_that_example_file_is_in_fake_fs()
-@pytest.mark.parametrize('fs', [[None, [example]]], indirect=True)
+@pytest.mark.parametrize("fs", [[None, [example]]], indirect=True)
def test_example_file_passing_using_parametrized_fixture(fs):
"""Test passes if using a fixture that reloads the module containing
EXAMPLE_FILE"""
- fs.create_file(example.EXAMPLE_FILE, contents='stuff here')
+ fs.create_file(example.EXAMPLE_FILE, contents="stuff here")
check_that_example_file_is_in_fake_fs()
def check_that_example_file_is_in_fake_fs():
with open(example.EXAMPLE_FILE) as file:
- assert file.read() == 'stuff here'
+ assert file.read() == "stuff here"
with example.EXAMPLE_FILE.open() as file:
- assert file.read() == 'stuff here'
- assert example.EXAMPLE_FILE.read_text() == 'stuff here'
+ assert file.read() == "stuff here"
+ assert example.EXAMPLE_FILE.read_text() == "stuff here"
assert example.EXAMPLE_FILE.is_file()
diff --git a/pyfakefs/pytest_tests/pytest_fixture_test.py b/pyfakefs/pytest_tests/pytest_fixture_test.py
index e69e61e..8bb377b 100644
--- a/pyfakefs/pytest_tests/pytest_fixture_test.py
+++ b/pyfakefs/pytest_tests/pytest_fixture_test.py
@@ -23,14 +23,14 @@ from pyfakefs.fake_filesystem_unittest import Patcher
def test_example_file_failing(fs):
"""Test fails because EXAMPLE_FILE is cached in the module
and not patched."""
- fs.create_file(example.EXAMPLE_FILE, contents='stuff here')
+ fs.create_file(example.EXAMPLE_FILE, contents="stuff here")
check_that_example_file_is_in_fake_fs()
def test_example_file_passing_using_fixture(fs_reload_example):
"""Test passes if using a fixture that reloads the module containing
EXAMPLE_FILE"""
- fs_reload_example.create_file(example.EXAMPLE_FILE, contents='stuff here')
+ fs_reload_example.create_file(example.EXAMPLE_FILE, contents="stuff here")
check_that_example_file_is_in_fake_fs()
@@ -38,14 +38,14 @@ def test_example_file_passing_using_patcher():
"""Test passes if using a Patcher instance that reloads the module
containing EXAMPLE_FILE"""
with Patcher(modules_to_reload=[example]) as patcher:
- patcher.fs.create_file(example.EXAMPLE_FILE, contents='stuff here')
+ patcher.fs.create_file(example.EXAMPLE_FILE, contents="stuff here")
check_that_example_file_is_in_fake_fs()
def check_that_example_file_is_in_fake_fs():
with open(example.EXAMPLE_FILE) as file:
- assert file.read() == 'stuff here'
+ assert file.read() == "stuff here"
with example.EXAMPLE_FILE.open() as file:
- assert file.read() == 'stuff here'
- assert example.EXAMPLE_FILE.read_text() == 'stuff here'
+ assert file.read() == "stuff here"
+ assert example.EXAMPLE_FILE.read_text() == "stuff here"
assert example.EXAMPLE_FILE.is_file()
diff --git a/pyfakefs/pytest_tests/pytest_module_fixture_test.py b/pyfakefs/pytest_tests/pytest_module_fixture_test.py
new file mode 100644
index 0000000..3140ec9
--- /dev/null
+++ b/pyfakefs/pytest_tests/pytest_module_fixture_test.py
@@ -0,0 +1,26 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import os
+
+import pytest
+
+
+@pytest.fixture(scope="module", autouse=True)
+def use_fs(fs_module):
+ fs_module.create_file(os.path.join("foo", "bar"))
+ yield fs_module
+
+
+@pytest.mark.usefixtures("fs")
+def test_fs_uses_fs_module():
+ # check that `fs` uses the same filesystem as `fs_module`
+ assert os.path.exists(os.path.join("foo", "bar"))
diff --git a/pyfakefs/pytest_tests/pytest_plugin_failing_helper.py b/pyfakefs/pytest_tests/pytest_plugin_failing_helper.py
index dd4bab8..0891018 100644
--- a/pyfakefs/pytest_tests/pytest_plugin_failing_helper.py
+++ b/pyfakefs/pytest_tests/pytest_plugin_failing_helper.py
@@ -3,4 +3,4 @@
def test_fs(fs):
- assert False
+ assert 1 == 2
diff --git a/pyfakefs/pytest_tests/pytest_plugin_test.py b/pyfakefs/pytest_tests/pytest_plugin_test.py
index 5632ff6..51f95cb 100644
--- a/pyfakefs/pytest_tests/pytest_plugin_test.py
+++ b/pyfakefs/pytest_tests/pytest_plugin_test.py
@@ -2,24 +2,26 @@
import os
import tempfile
+from pyfakefs.fake_filesystem import OSType
from pyfakefs.fake_filesystem_unittest import Pause
+import pyfakefs.pytest_tests.io
def test_fs_fixture(fs):
- fs.create_file('/var/data/xx1.txt')
- assert os.path.exists('/var/data/xx1.txt')
+ fs.create_file("/var/data/xx1.txt")
+ assert os.path.exists("/var/data/xx1.txt")
def test_fs_fixture_alias(fake_filesystem):
- fake_filesystem.create_file('/var/data/xx1.txt')
- assert os.path.exists('/var/data/xx1.txt')
+ fake_filesystem.create_file("/var/data/xx1.txt")
+ assert os.path.exists("/var/data/xx1.txt")
def test_both_fixtures(fs, fake_filesystem):
- fake_filesystem.create_file('/var/data/xx1.txt')
- fs.create_file('/var/data/xx2.txt')
- assert os.path.exists('/var/data/xx1.txt')
- assert os.path.exists('/var/data/xx2.txt')
+ fake_filesystem.create_file("/var/data/xx1.txt")
+ fs.create_file("/var/data/xx2.txt")
+ assert os.path.exists("/var/data/xx1.txt")
+ assert os.path.exists("/var/data/xx2.txt")
assert fs == fake_filesystem
@@ -50,3 +52,27 @@ def test_pause_resume_contextmanager(fs):
assert os.path.exists(real_temp_file.name)
assert not os.path.exists(real_temp_file.name)
assert os.path.exists(fake_temp_file.name)
+
+
+def test_use_own_io_module(fs):
+ filepath = "foo.txt"
+ with open(filepath, "w") as f:
+ f.write("bar")
+
+ stream = pyfakefs.pytest_tests.io.InputStream(filepath)
+ assert stream.read() == "bar"
+
+
+def test_switch_to_windows(fs):
+ fs.os = OSType.WINDOWS
+ assert os.path.exists(tempfile.gettempdir())
+
+
+def test_switch_to_linux(fs):
+ fs.os = OSType.LINUX
+ assert os.path.exists(tempfile.gettempdir())
+
+
+def test_switch_to_macos(fs):
+ fs.os = OSType.MACOS
+ assert os.path.exists(tempfile.gettempdir())
diff --git a/pyfakefs/pytest_tests/segfault_test.py b/pyfakefs/pytest_tests/segfault_test.py
new file mode 100644
index 0000000..05f46dc
--- /dev/null
+++ b/pyfakefs/pytest_tests/segfault_test.py
@@ -0,0 +1,16 @@
+"""
+This is a regression test for #866 that shall ensure that
+shutting down the test session after this specific call does not result
+in a segmentation fault.
+"""
+import opentimelineio as otio
+
+
+def test_empty_fs(fs):
+ pass
+
+
+def test_create_clip(fs):
+ """If the fs cache is not cleared during session shutdown, a segmentation fault
+ will happen during garbage collection of the cached modules."""
+ otio.core.SerializableObjectWithMetadata(metadata={})
diff --git a/pyfakefs/tests/all_tests.py b/pyfakefs/tests/all_tests.py
index 331a3d1..36945af 100644
--- a/pyfakefs/tests/all_tests.py
+++ b/pyfakefs/tests/all_tests.py
@@ -32,7 +32,7 @@ from pyfakefs.tests import (
fake_pathlib_test,
fake_tempfile_test,
patched_packages_test,
- mox3_stubout_test
+ mox3_stubout_test,
)
@@ -41,25 +41,27 @@ class AllTests(unittest.TestSuite):
def suite(self): # pylint: disable-msg=C6409
loader = unittest.defaultTestLoader
- self.addTests([
- loader.loadTestsFromModule(fake_filesystem_test),
- loader.loadTestsFromModule(fake_filesystem_glob_test),
- loader.loadTestsFromModule(fake_filesystem_shutil_test),
- loader.loadTestsFromModule(fake_os_test),
- loader.loadTestsFromModule(fake_stat_time_test),
- loader.loadTestsFromModule(fake_open_test),
- loader.loadTestsFromModule(fake_tempfile_test),
- loader.loadTestsFromModule(fake_filesystem_vs_real_test),
- loader.loadTestsFromModule(fake_filesystem_unittest_test),
- loader.loadTestsFromModule(example_test),
- loader.loadTestsFromModule(mox3_stubout_test),
- loader.loadTestsFromModule(dynamic_patch_test),
- loader.loadTestsFromModule(fake_pathlib_test),
- loader.loadTestsFromModule(patched_packages_test)
- ])
+ self.addTests(
+ [
+ loader.loadTestsFromModule(fake_filesystem_test),
+ loader.loadTestsFromModule(fake_filesystem_glob_test),
+ loader.loadTestsFromModule(fake_filesystem_shutil_test),
+ loader.loadTestsFromModule(fake_os_test),
+ loader.loadTestsFromModule(fake_stat_time_test),
+ loader.loadTestsFromModule(fake_open_test),
+ loader.loadTestsFromModule(fake_tempfile_test),
+ loader.loadTestsFromModule(fake_filesystem_vs_real_test),
+ loader.loadTestsFromModule(fake_filesystem_unittest_test),
+ loader.loadTestsFromModule(example_test),
+ loader.loadTestsFromModule(mox3_stubout_test),
+ loader.loadTestsFromModule(dynamic_patch_test),
+ loader.loadTestsFromModule(fake_pathlib_test),
+ loader.loadTestsFromModule(patched_packages_test),
+ ]
+ )
return self
-if __name__ == '__main__':
+if __name__ == "__main__":
result = unittest.TextTestRunner(verbosity=2).run(AllTests().suite())
sys.exit(int(not result.wasSuccessful()))
diff --git a/pyfakefs/tests/all_tests_without_extra_packages.py b/pyfakefs/tests/all_tests_without_extra_packages.py
index 3d65e9d..8927802 100644
--- a/pyfakefs/tests/all_tests_without_extra_packages.py
+++ b/pyfakefs/tests/all_tests_without_extra_packages.py
@@ -29,6 +29,6 @@ if extra_packages.use_scandir_package:
from pyfakefs.tests.all_tests import AllTests # noqa: E402
-if __name__ == '__main__':
+if __name__ == "__main__":
result = unittest.TextTestRunner(verbosity=2).run(AllTests().suite())
sys.exit(int(not result.wasSuccessful()))
diff --git a/pyfakefs/tests/dynamic_patch_test.py b/pyfakefs/tests/dynamic_patch_test.py
index 132dd0a..bb8ac40 100644
--- a/pyfakefs/tests/dynamic_patch_test.py
+++ b/pyfakefs/tests/dynamic_patch_test.py
@@ -26,45 +26,45 @@ class TestPyfakefsUnittestBase(fake_filesystem_unittest.TestCase):
class DynamicImportPatchTest(TestPyfakefsUnittestBase):
- def __init__(self, methodName='runTest'):
+ def __init__(self, methodName="runTest"):
super(DynamicImportPatchTest, self).__init__(methodName)
def test_os_patch(self):
import os
- os.mkdir('test')
- self.assertTrue(self.fs.exists('test'))
- self.assertTrue(os.path.exists('test'))
+ os.mkdir("test")
+ self.assertTrue(self.fs.exists("test"))
+ self.assertTrue(os.path.exists("test"))
def test_os_import_as_patch(self):
import os as _os
- _os.mkdir('test')
- self.assertTrue(self.fs.exists('test'))
- self.assertTrue(_os.path.exists('test'))
+ _os.mkdir("test")
+ self.assertTrue(self.fs.exists("test"))
+ self.assertTrue(_os.path.exists("test"))
def test_os_path_patch(self):
import os.path
- os.mkdir('test')
- self.assertTrue(self.fs.exists('test'))
- self.assertTrue(os.path.exists('test'))
+ os.mkdir("test")
+ self.assertTrue(self.fs.exists("test"))
+ self.assertTrue(os.path.exists("test"))
def test_shutil_patch(self):
import shutil
self.fs.set_disk_usage(100)
- self.assertEqual(100, shutil.disk_usage('/').total)
+ self.assertEqual(100, shutil.disk_usage("/").total)
def test_pathlib_path_patch(self):
- file_path = 'test.txt'
+ file_path = "test.txt"
path = pathlib.Path(file_path)
- with path.open('w') as f:
- f.write('test')
+ with path.open("w") as f:
+ f.write("test")
self.assertTrue(self.fs.exists(file_path))
file_object = self.fs.get_object(file_path)
- self.assertEqual('test', file_object.contents)
+ self.assertEqual("test", file_object.contents)
if __name__ == "__main__":
diff --git a/pyfakefs/tests/example.py b/pyfakefs/tests/example.py
index 09d7a3d..4ab9921 100644
--- a/pyfakefs/tests/example.py
+++ b/pyfakefs/tests/example.py
@@ -21,9 +21,9 @@ This demonstrates the usage of the
The modules related to file handling are bound to the respective fake modules:
>>> os #doctest: +ELLIPSIS
-<pyfakefs.fake_filesystem.FakeOsModule object...>
+<pyfakefs.fake_os.FakeOsModule object...>
>>> os.path #doctest: +ELLIPSIS
-<pyfakefs.fake_filesystem.FakePathModule object...>
+<pyfakefs.fake_path.FakePathModule object...>
>>> shutil #doctest: +ELLIPSIS
<pyfakefs.fake_filesystem_shutil.FakeShutilModule object...>
@@ -36,6 +36,7 @@ import shutil
try:
import scandir
+
has_scandir = True
except ImportError:
scandir = None
@@ -65,7 +66,7 @@ def create_file(path):
["This is test file '/test/file.txt'.\\n", \
'It was created using open().\\n']
"""
- with open(path, 'w') as f:
+ with open(path, "w") as f:
f.write("This is test file '{0}'.\n".format(path))
f.write("It was created using open().\n")
@@ -144,5 +145,5 @@ def scan_dir(path):
def file_contents(path):
"""Return the contents of the given path as byte array."""
- with open(path, 'rb') as f:
+ with open(path, "rb") as f:
return f.read()
diff --git a/pyfakefs/tests/example_test.py b/pyfakefs/tests/example_test.py
index 91225d0..126bbe7 100644
--- a/pyfakefs/tests/example_test.py
+++ b/pyfakefs/tests/example_test.py
@@ -38,15 +38,14 @@ from pyfakefs.tests import example # The module under test
def load_tests(loader, tests, ignore):
"""Load the pyfakefs/example.py doctest tests into unittest."""
- return fake_filesystem_unittest.load_doctests(
- loader, tests, ignore, example)
+ return fake_filesystem_unittest.load_doctests(loader, tests, ignore, example)
class TestExample(fake_filesystem_unittest.TestCase): # pylint: disable=R0904
"""Test the example module.
- The os and shutil modules have been replaced with the fake modules,
- so that all of the calls to os and shutil in the tested example code
- occur in the fake filesystem.
+ The os and shutil modules have been replaced with the fake modules,
+ so that all of the calls to os and shutil in the tested example code
+ occur in the fake filesystem.
"""
def setUp(self):
@@ -63,7 +62,7 @@ class TestExample(fake_filesystem_unittest.TestCase): # pylint: disable=R0904
# This is before setUpPyfakefs(), so still using the real file system
self.filepath = os.path.realpath(__file__)
- with io.open(self.filepath, 'rb') as f:
+ with io.open(self.filepath, "rb") as f:
self.real_contents = f.read()
self.setUpPyfakefs()
@@ -73,61 +72,57 @@ class TestExample(fake_filesystem_unittest.TestCase): # pylint: disable=R0904
pass
def test_create_file(self):
- """Test example.create_file() which uses `open()` and `file.write()`.
+ """Test example.create_file() which uses `open()`
+ and `file.write()`.
"""
- self.assertFalse(os.path.isdir('/test'))
- os.mkdir('/test')
- self.assertTrue(os.path.isdir('/test'))
+ self.assertFalse(os.path.isdir("/test"))
+ os.mkdir("/test")
+ self.assertTrue(os.path.isdir("/test"))
- self.assertFalse(os.path.exists('/test/file.txt'))
- example.create_file('/test/file.txt')
- self.assertTrue(os.path.exists('/test/file.txt'))
+ self.assertFalse(os.path.exists("/test/file.txt"))
+ example.create_file("/test/file.txt")
+ self.assertTrue(os.path.exists("/test/file.txt"))
def test_delete_file(self):
"""Test example.delete_file() which uses `os.remove()`."""
- self.fs.create_file('/test/full.txt',
- contents='First line\n'
- 'Second Line\n')
- self.assertTrue(os.path.exists('/test/full.txt'))
- example.delete_file('/test/full.txt')
- self.assertFalse(os.path.exists('/test/full.txt'))
+ self.fs.create_file("/test/full.txt", contents="First line\n" "Second Line\n")
+ self.assertTrue(os.path.exists("/test/full.txt"))
+ example.delete_file("/test/full.txt")
+ self.assertFalse(os.path.exists("/test/full.txt"))
def test_file_exists(self):
"""Test example.path_exists() which uses `os.path.exists()`."""
- self.assertFalse(example.path_exists('/test/empty.txt'))
- self.fs.create_file('/test/empty.txt')
- self.assertTrue(example.path_exists('/test/empty.txt'))
+ self.assertFalse(example.path_exists("/test/empty.txt"))
+ self.fs.create_file("/test/empty.txt")
+ self.assertTrue(example.path_exists("/test/empty.txt"))
def test_get_globs(self):
"""Test example.get_glob()."""
- self.assertFalse(os.path.isdir('/test'))
- self.fs.create_dir('/test/dir1/dir2a')
- self.assertTrue(os.path.isdir('/test/dir1/dir2a'))
+ self.assertFalse(os.path.isdir("/test"))
+ self.fs.create_dir("/test/dir1/dir2a")
+ self.assertTrue(os.path.isdir("/test/dir1/dir2a"))
# os.mkdirs() works, too.
- os.makedirs('/test/dir1/dir2b')
- self.assertTrue(os.path.isdir('/test/dir1/dir2b'))
+ os.makedirs("/test/dir1/dir2b")
+ self.assertTrue(os.path.isdir("/test/dir1/dir2b"))
- self.assertEqual(example.get_glob('/test/dir1/nonexistent*'),
- [])
- is_windows = sys.platform.startswith('win')
- matching_paths = sorted(example.get_glob('/test/dir1/dir*'))
+ self.assertEqual(example.get_glob("/test/dir1/nonexistent*"), [])
+ is_windows = sys.platform.startswith("win")
+ matching_paths = sorted(example.get_glob("/test/dir1/dir*"))
if is_windows:
- self.assertEqual(matching_paths,
- [r'/test/dir1\dir2a', r'/test/dir1\dir2b'])
+ self.assertEqual(matching_paths, [r"/test/dir1\dir2a", r"/test/dir1\dir2b"])
else:
- self.assertEqual(matching_paths,
- ['/test/dir1/dir2a', '/test/dir1/dir2b'])
+ self.assertEqual(matching_paths, ["/test/dir1/dir2a", "/test/dir1/dir2b"])
def test_rm_tree(self):
"""Test example.rm_tree() using `shutil.rmtree()`."""
- self.fs.create_dir('/test/dir1/dir2a')
+ self.fs.create_dir("/test/dir1/dir2a")
# os.mkdirs() works, too.
- os.makedirs('/test/dir1/dir2b')
- self.assertTrue(os.path.isdir('/test/dir1/dir2b'))
- self.assertTrue(os.path.isdir('/test/dir1/dir2a'))
+ os.makedirs("/test/dir1/dir2b")
+ self.assertTrue(os.path.isdir("/test/dir1/dir2b"))
+ self.assertTrue(os.path.isdir("/test/dir1/dir2a"))
- example.rm_tree('/test/dir1')
- self.assertFalse(os.path.exists('/test/dir1'))
+ example.rm_tree("/test/dir1")
+ self.assertFalse(os.path.exists("/test/dir1"))
def test_os_scandir(self):
"""Test example.scandir() which uses `os.scandir()`.
@@ -136,20 +131,21 @@ class TestExample(fake_filesystem_unittest.TestCase): # pylint: disable=R0904
fake filesystem path entries are returned instead of `os.DirEntry`
objects.
"""
- self.fs.create_file('/test/text.txt')
- self.fs.create_dir('/test/dir')
- self.fs.create_file('/linktest/linked')
- self.fs.create_symlink('/test/linked_file', '/linktest/linked')
+ self.fs.create_file("/test/text.txt")
+ self.fs.create_dir("/test/dir")
+ self.fs.create_file("/linktest/linked")
+ self.fs.create_symlink("/test/linked_file", "/linktest/linked")
- entries = sorted(example.scan_dir('/test'), key=lambda e: e.name)
+ entries = sorted(example.scan_dir("/test"), key=lambda e: e.name)
self.assertEqual(3, len(entries))
- self.assertEqual('linked_file', entries[1].name)
+ self.assertEqual("linked_file", entries[1].name)
self.assertTrue(entries[0].is_dir())
self.assertTrue(entries[1].is_symlink())
self.assertTrue(entries[2].is_file())
- @unittest.skipIf(not use_scandir_package,
- 'Testing only if scandir module is installed')
+ @unittest.skipIf(
+ not use_scandir_package, "Testing only if scandir module is installed"
+ )
def test_scandir_scandir(self):
"""Test example.scandir() which uses `scandir.scandir()`.
@@ -157,23 +153,22 @@ class TestExample(fake_filesystem_unittest.TestCase): # pylint: disable=R0904
the fake filesystem path entries are returned instead of
`scandir.DirEntry` objects.
"""
- self.fs.create_file('/test/text.txt')
- self.fs.create_dir('/test/dir')
+ self.fs.create_file("/test/text.txt")
+ self.fs.create_dir("/test/dir")
- entries = sorted(example.scan_dir('/test'), key=lambda e: e.name)
+ entries = sorted(example.scan_dir("/test"), key=lambda e: e.name)
self.assertEqual(2, len(entries))
- self.assertEqual('text.txt', entries[1].name)
+ self.assertEqual("text.txt", entries[1].name)
self.assertTrue(entries[0].is_dir())
self.assertTrue(entries[1].is_file())
def test_real_file_access(self):
"""Test `example.file_contents()` for a real file after adding it using
- `add_real_file()`."""
+ `add_real_file()`."""
with self.assertRaises(OSError):
example.file_contents(self.filepath)
self.fs.add_real_file(self.filepath)
- self.assertEqual(example.file_contents(self.filepath),
- self.real_contents)
+ self.assertEqual(example.file_contents(self.filepath), self.real_contents)
if __name__ == "__main__":
diff --git a/pyfakefs/tests/fake_filesystem_glob_test.py b/pyfakefs/tests/fake_filesystem_glob_test.py
index 7432fa8..1ca141f 100644
--- a/pyfakefs/tests/fake_filesystem_glob_test.py
+++ b/pyfakefs/tests/fake_filesystem_glob_test.py
@@ -24,51 +24,59 @@ from pyfakefs import fake_filesystem_unittest
class FakeGlobUnitTest(fake_filesystem_unittest.TestCase):
def setUp(self):
self.setUpPyfakefs()
- directory = './xyzzy'
+ directory = "./xyzzy"
self.fs.create_dir(directory)
- self.fs.create_dir('%s/subdir' % directory)
- self.fs.create_dir('%s/subdir2' % directory)
- self.fs.create_file('%s/subfile' % directory)
- self.fs.create_file('[Temp]')
+ self.fs.create_dir("%s/subdir" % directory)
+ self.fs.create_dir("%s/subdir2" % directory)
+ self.fs.create_file("%s/subfile" % directory)
+ self.fs.create_file("[Temp]")
def test_glob_empty(self):
- self.assertEqual(glob.glob(''), [])
+ self.assertEqual(glob.glob(""), [])
def test_glob_star(self):
- basedir = '/xyzzy'
- self.assertEqual([os.path.join(basedir, 'subdir'),
- os.path.join(basedir, 'subdir2'),
- os.path.join(basedir, 'subfile')],
- sorted(glob.glob('/xyzzy/*')))
+ basedir = "/xyzzy"
+ self.assertEqual(
+ [
+ os.path.join(basedir, "subdir"),
+ os.path.join(basedir, "subdir2"),
+ os.path.join(basedir, "subfile"),
+ ],
+ sorted(glob.glob("/xyzzy/*")),
+ )
def test_glob_exact(self):
- self.assertEqual(['/xyzzy'], glob.glob('/xyzzy'))
- self.assertEqual(['/xyzzy/subfile'], glob.glob('/xyzzy/subfile'))
+ self.assertEqual(["/xyzzy"], glob.glob("/xyzzy"))
+ self.assertEqual(["/xyzzy/subfile"], glob.glob("/xyzzy/subfile"))
def test_glob_question(self):
- basedir = '/xyzzy'
- self.assertEqual([os.path.join(basedir, 'subdir'),
- os.path.join(basedir, 'subdir2'),
- os.path.join(basedir, 'subfile')],
- sorted(glob.glob('/x?zz?/*')))
+ basedir = "/xyzzy"
+ self.assertEqual(
+ [
+ os.path.join(basedir, "subdir"),
+ os.path.join(basedir, "subdir2"),
+ os.path.join(basedir, "subfile"),
+ ],
+ sorted(glob.glob("/x?zz?/*")),
+ )
def test_glob_no_magic(self):
- self.assertEqual(['/xyzzy'], glob.glob('/xyzzy'))
- self.assertEqual(['/xyzzy/subdir'], glob.glob('/xyzzy/subdir'))
+ self.assertEqual(["/xyzzy"], glob.glob("/xyzzy"))
+ self.assertEqual(["/xyzzy/subdir"], glob.glob("/xyzzy/subdir"))
def test_non_existent_path(self):
- self.assertEqual([], glob.glob('nonexistent'))
+ self.assertEqual([], glob.glob("nonexistent"))
def test_magic_dir(self):
- self.assertEqual(['/[Temp]'], glob.glob('/*emp*'))
+ self.assertEqual(["/[Temp]"], glob.glob("/*emp*"))
def test_glob1(self):
- self.assertEqual(['[Temp]'], glob.glob1('/', '*Tem*'))
+ self.assertEqual(["[Temp]"], glob.glob1("/", "*Tem*"))
def test_has_magic(self):
- self.assertTrue(glob.has_magic('['))
- self.assertFalse(glob.has_magic('a'))
+ self.assertTrue(glob.has_magic("["))
+ self.assertFalse(glob.has_magic("a"))
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
diff --git a/pyfakefs/tests/fake_filesystem_shutil_test.py b/pyfakefs/tests/fake_filesystem_shutil_test.py
index 5861e63..83d4672 100644
--- a/pyfakefs/tests/fake_filesystem_shutil_test.py
+++ b/pyfakefs/tests/fake_filesystem_shutil_test.py
@@ -22,23 +22,24 @@ import shutil
import sys
import tempfile
import unittest
+from pathlib import Path
from pyfakefs import fake_filesystem_unittest
-from pyfakefs.fake_filesystem import is_root, set_uid, USER_ID
+from pyfakefs.helpers import get_uid, set_uid, is_root, IS_PYPY
from pyfakefs.tests.test_utils import RealFsTestMixin
-is_windows = sys.platform == 'win32'
+is_windows = sys.platform == "win32"
class RealFsTestCase(fake_filesystem_unittest.TestCase, RealFsTestMixin):
- def __init__(self, methodName='runTest'):
+ def __init__(self, methodName="runTest"):
fake_filesystem_unittest.TestCase.__init__(self, methodName)
RealFsTestMixin.__init__(self)
def setUp(self):
RealFsTestMixin.setUp(self)
self.cwd = os.getcwd()
- self.uid = USER_ID
+ self.uid = get_uid()
set_uid(1000)
if not self.use_real_fs():
self.setUpPyfakefs()
@@ -55,32 +56,32 @@ class RealFsTestCase(fake_filesystem_unittest.TestCase, RealFsTestMixin):
@property
def is_windows_fs(self):
if self.use_real_fs():
- return sys.platform == 'win32'
+ return sys.platform == "win32"
return self.filesystem.is_windows_fs
class FakeShutilModuleTest(RealFsTestCase):
- @unittest.skipIf(is_windows, 'Posix specific behavior')
+ @unittest.skipIf(is_windows, "Posix specific behavior")
def test_catch_permission_error(self):
- root_path = self.make_path('rootpath')
+ root_path = self.make_path("rootpath")
self.create_dir(root_path)
- dir1_path = self.os.path.join(root_path, 'dir1')
- dir2_path = self.os.path.join(root_path, 'dir2')
+ dir1_path = self.os.path.join(root_path, "dir1")
+ dir2_path = self.os.path.join(root_path, "dir2")
self.create_dir(dir1_path)
self.os.chmod(dir1_path, 0o555) # remove write permissions
self.create_dir(dir2_path)
- old_file_path = self.os.path.join(dir2_path, 'f1.txt')
- new_file_path = self.os.path.join(dir1_path, 'f1.txt')
+ old_file_path = self.os.path.join(dir2_path, "f1.txt")
+ new_file_path = self.os.path.join(dir1_path, "f1.txt")
self.create_file(old_file_path)
with self.assertRaises(PermissionError):
shutil.move(old_file_path, new_file_path)
def test_rmtree(self):
- directory = self.make_path('xyzzy')
- dir_path = os.path.join(directory, 'subdir')
+ directory = self.make_path("xyzzy")
+ dir_path = os.path.join(directory, "subdir")
self.create_dir(dir_path)
- file_path = os.path.join(directory, 'subfile')
+ file_path = os.path.join(directory, "subfile")
self.create_file(file_path)
self.assertTrue(os.path.exists(directory))
shutil.rmtree(directory)
@@ -89,22 +90,22 @@ class FakeShutilModuleTest(RealFsTestCase):
self.assertFalse(os.path.exists(file_path))
def test_rmtree_with_trailing_slash(self):
- directory = self.make_path('xyzzy')
- dir_path = os.path.join(directory, 'subdir')
+ directory = self.make_path("xyzzy")
+ dir_path = os.path.join(directory, "subdir")
self.create_dir(dir_path)
- file_path = os.path.join(directory, 'subfile')
+ file_path = os.path.join(directory, "subfile")
self.create_file(file_path)
- shutil.rmtree(directory + '/')
+ shutil.rmtree(directory + "/")
self.assertFalse(os.path.exists(directory))
self.assertFalse(os.path.exists(dir_path))
self.assertFalse(os.path.exists(file_path))
- @unittest.skipIf(not is_windows, 'Windows specific behavior')
+ @unittest.skipIf(not is_windows, "Windows specific behavior")
def test_rmtree_without_permission_for_a_file_in_windows(self):
self.check_windows_only()
- dir_path = self.make_path('foo')
- self.create_file(os.path.join(dir_path, 'bar'))
- file_path = os.path.join(dir_path, 'baz')
+ dir_path = self.make_path("foo")
+ self.create_file(os.path.join(dir_path, "bar"))
+ file_path = os.path.join(dir_path, "baz")
self.create_file(file_path)
self.os.chmod(file_path, 0o444)
with self.assertRaises(OSError):
@@ -112,12 +113,12 @@ class FakeShutilModuleTest(RealFsTestCase):
self.assertTrue(os.path.exists(file_path))
self.os.chmod(file_path, 0o666)
- @unittest.skipIf(is_windows, 'Posix specific behavior')
+ @unittest.skipIf(is_windows, "Posix specific behavior")
def test_rmtree_without_permission_for_a_dir_in_posix(self):
self.check_posix_only()
- dir_path = self.make_path('foo')
- self.create_file(os.path.join(dir_path, 'bar'))
- file_path = os.path.join(dir_path, 'baz')
+ dir_path = self.make_path("foo")
+ self.create_file(os.path.join(dir_path, "bar"))
+ file_path = os.path.join(dir_path, "baz")
self.create_file(file_path)
self.os.chmod(dir_path, 0o555)
if not is_root():
@@ -129,23 +130,23 @@ class FakeShutilModuleTest(RealFsTestCase):
shutil.rmtree(dir_path)
self.assertFalse(os.path.exists(file_path))
- @unittest.skipIf(is_windows, 'Posix specific behavior')
+ @unittest.skipIf(is_windows, "Posix specific behavior")
def test_rmtree_with_open_file_posix(self):
self.check_posix_only()
- dir_path = self.make_path('foo')
- self.create_file(os.path.join(dir_path, 'bar'))
- file_path = os.path.join(dir_path, 'baz')
+ dir_path = self.make_path("foo")
+ self.create_file(os.path.join(dir_path, "bar"))
+ file_path = os.path.join(dir_path, "baz")
self.create_file(file_path)
with open(file_path):
shutil.rmtree(dir_path)
self.assertFalse(os.path.exists(file_path))
- @unittest.skipIf(not is_windows, 'Windows specific behavior')
+ @unittest.skipIf(not is_windows, "Windows specific behavior")
def test_rmtree_with_open_file_fails_under_windows(self):
self.check_windows_only()
- dir_path = self.make_path('foo')
- self.create_file(os.path.join(dir_path, 'bar'))
- file_path = os.path.join(dir_path, 'baz')
+ dir_path = self.make_path("foo")
+ self.create_file(os.path.join(dir_path, "bar"))
+ file_path = os.path.join(dir_path, "baz")
self.create_file(file_path)
with open(file_path):
with self.assertRaises(OSError):
@@ -153,13 +154,13 @@ class FakeShutilModuleTest(RealFsTestCase):
self.assertTrue(os.path.exists(dir_path))
def test_rmtree_non_existing_dir(self):
- directory = 'nonexisting'
+ directory = "nonexisting"
with self.assertRaises(OSError):
shutil.rmtree(directory)
try:
shutil.rmtree(directory, ignore_errors=True)
except OSError:
- self.fail('rmtree raised despite ignore_errors True')
+ self.fail("rmtree raised despite ignore_errors True")
def test_rmtree_non_existing_dir_with_handler(self):
class NonLocal:
@@ -169,30 +170,30 @@ class FakeShutilModuleTest(RealFsTestCase):
NonLocal.errorHandled = True
NonLocal.errorPath = path
- directory = self.make_path('nonexisting')
+ directory = self.make_path("nonexisting")
NonLocal.errorHandled = False
- NonLocal.errorPath = ''
+ NonLocal.errorPath = ""
try:
shutil.rmtree(directory, onerror=error_handler)
except OSError:
- self.fail('rmtree raised exception despite onerror defined')
+ self.fail("rmtree raised exception despite onerror defined")
self.assertTrue(NonLocal.errorHandled)
self.assertEqual(NonLocal.errorPath, directory)
NonLocal.errorHandled = False
- NonLocal.errorPath = ''
+ NonLocal.errorPath = ""
try:
shutil.rmtree(directory, ignore_errors=True, onerror=error_handler)
except OSError:
- self.fail('rmtree raised exception despite ignore_errors True')
+ self.fail("rmtree raised exception despite ignore_errors True")
# ignore_errors is True, so the onerror() error handler was
# not executed
self.assertFalse(NonLocal.errorHandled)
- self.assertEqual(NonLocal.errorPath, '')
+ self.assertEqual(NonLocal.errorPath, "")
def test_copy(self):
- src_file = self.make_path('xyzzy')
- dst_file = self.make_path('xyzzy_copy')
+ src_file = self.make_path("xyzzy")
+ dst_file = self.make_path("xyzzy_copy")
self.create_file(src_file)
os.chmod(src_file, 0o750)
self.assertTrue(os.path.exists(src_file))
@@ -202,9 +203,9 @@ class FakeShutilModuleTest(RealFsTestCase):
self.assertEqual(os.stat(src_file).st_mode, os.stat(dst_file).st_mode)
def test_copy_directory(self):
- src_file = self.make_path('xyzzy')
- parent_directory = self.make_path('parent')
- dst_file = os.path.join(parent_directory, 'xyzzy')
+ src_file = self.make_path("xyzzy")
+ parent_directory = self.make_path("parent")
+ dst_file = os.path.join(parent_directory, "xyzzy")
self.create_file(src_file)
self.create_dir(parent_directory)
os.chmod(src_file, 0o750)
@@ -216,10 +217,10 @@ class FakeShutilModuleTest(RealFsTestCase):
self.assertEqual(os.stat(src_file).st_mode, os.stat(dst_file).st_mode)
def test_copystat(self):
- src_file = self.make_path('xyzzy')
+ src_file = self.make_path("xyzzy")
self.create_file(src_file)
os.chmod(src_file, 0o750)
- dst_file = self.make_path('xyzzy_copy')
+ dst_file = self.make_path("xyzzy_copy")
self.create_file(dst_file)
self.assertTrue(os.path.exists(src_file))
self.assertTrue(os.path.exists(dst_file))
@@ -230,11 +231,23 @@ class FakeShutilModuleTest(RealFsTestCase):
self.assertAlmostEqual(src_stat.st_atime, dst_stat.st_atime, places=2)
self.assertAlmostEqual(src_stat.st_mtime, dst_stat.st_mtime, places=2)
+ @unittest.skipIf(IS_PYPY, "Functionality not supported in PyPy")
+ def test_copystat_symlinks(self):
+ """Regression test for #799"""
+ self.skip_if_symlink_not_supported()
+ f = self.make_path("xyzzy")
+ self.create_file(f)
+ sym1 = self.make_path("sym1")
+ sym2 = self.make_path("sym2")
+ self.create_symlink(sym1, f)
+ self.create_symlink(sym2, f)
+ shutil.copystat(sym1, sym2, follow_symlinks=False)
+
def test_copy2(self):
- src_file = self.make_path('xyzzy')
+ src_file = self.make_path("xyzzy")
self.create_file(src_file)
os.chmod(src_file, 0o750)
- dst_file = self.make_path('xyzzy_copy')
+ dst_file = self.make_path("xyzzy_copy")
self.assertTrue(os.path.exists(src_file))
self.assertFalse(os.path.exists(dst_file))
shutil.copy2(src_file, dst_file)
@@ -246,9 +259,9 @@ class FakeShutilModuleTest(RealFsTestCase):
self.assertAlmostEqual(src_stat.st_mtime, dst_stat.st_mtime, places=2)
def test_copy2_directory(self):
- src_file = self.make_path('xyzzy')
- parent_directory = self.make_path('parent')
- dst_file = os.path.join(parent_directory, 'xyzzy')
+ src_file = self.make_path("xyzzy")
+ parent_directory = self.make_path("parent")
+ dst_file = os.path.join(parent_directory, "xyzzy")
self.create_file(src_file)
self.create_dir(parent_directory)
os.chmod(src_file, 0o750)
@@ -264,21 +277,21 @@ class FakeShutilModuleTest(RealFsTestCase):
self.assertAlmostEqual(src_stat.st_mtime, dst_stat.st_mtime, places=2)
def test_copytree(self):
- src_directory = self.make_path('xyzzy')
- dst_directory = self.make_path('xyzzy_copy')
+ src_directory = self.make_path("xyzzy")
+ dst_directory = self.make_path("xyzzy_copy")
self.create_dir(src_directory)
- self.create_dir('%s/subdir' % src_directory)
- self.create_file(os.path.join(src_directory, 'subfile'))
+ self.create_dir("%s/subdir" % src_directory)
+ self.create_file(os.path.join(src_directory, "subfile"))
self.assertTrue(os.path.exists(src_directory))
self.assertFalse(os.path.exists(dst_directory))
shutil.copytree(src_directory, dst_directory)
self.assertTrue(os.path.exists(dst_directory))
- self.assertTrue(os.path.exists(os.path.join(dst_directory, 'subdir')))
- self.assertTrue(os.path.exists(os.path.join(dst_directory, 'subfile')))
+ self.assertTrue(os.path.exists(os.path.join(dst_directory, "subdir")))
+ self.assertTrue(os.path.exists(os.path.join(dst_directory, "subfile")))
def test_copytree_src_is_file(self):
- src_file = self.make_path('xyzzy')
- dst_directory = self.make_path('xyzzy_copy')
+ src_file = self.make_path("xyzzy")
+ dst_directory = self.make_path("xyzzy_copy")
self.create_file(src_file)
self.assertTrue(os.path.exists(src_file))
self.assertFalse(os.path.exists(dst_directory))
@@ -287,8 +300,8 @@ class FakeShutilModuleTest(RealFsTestCase):
def test_move_file_in_same_filesystem(self):
self.skip_real_fs()
- src_file = '/original_xyzzy'
- dst_file = '/moved_xyzzy'
+ src_file = "/original_xyzzy"
+ dst_file = "/moved_xyzzy"
src_object = self.fs.create_file(src_file)
src_ino = src_object.st_ino
src_dev = src_object.st_dev
@@ -307,8 +320,8 @@ class FakeShutilModuleTest(RealFsTestCase):
self.skip_real_fs()
mount_point = self.create_mount_point()
- src_file = self.make_path('original_xyzzy')
- dst_file = self.os.path.join(mount_point, 'moved_xyzzy')
+ src_file = self.make_path("original_xyzzy")
+ dst_file = self.os.path.join(mount_point, "moved_xyzzy")
src_object = self.fs.create_file(src_file)
src_ino = src_object.st_ino
src_dev = src_object.st_dev
@@ -322,9 +335,9 @@ class FakeShutilModuleTest(RealFsTestCase):
self.assertNotEqual(src_dev, dst_object.st_dev)
def test_move_file_into_directory(self):
- src_file = self.make_path('xyzzy')
- dst_directory = self.make_path('directory')
- dst_file = os.path.join(dst_directory, 'xyzzy')
+ src_file = self.make_path("xyzzy")
+ dst_directory = self.make_path("directory")
+ dst_file = os.path.join(dst_directory, "xyzzy")
self.create_file(src_file)
self.create_dir(dst_directory)
self.assertTrue(os.path.exists(src_file))
@@ -334,24 +347,23 @@ class FakeShutilModuleTest(RealFsTestCase):
self.assertFalse(os.path.exists(src_file))
def test_move_directory(self):
- src_directory = self.make_path('original_xyzzy')
- dst_directory = self.make_path('moved_xyzzy')
+ src_directory = self.make_path("original_xyzzy")
+ dst_directory = self.make_path("moved_xyzzy")
self.create_dir(src_directory)
- self.create_file(os.path.join(src_directory, 'subfile'))
- self.create_dir(os.path.join(src_directory, 'subdir'))
+ self.create_file(os.path.join(src_directory, "subfile"))
+ self.create_dir(os.path.join(src_directory, "subdir"))
self.assertTrue(os.path.exists(src_directory))
self.assertFalse(os.path.exists(dst_directory))
shutil.move(src_directory, dst_directory)
self.assertTrue(os.path.exists(dst_directory))
- self.assertTrue(os.path.exists(os.path.join(dst_directory, 'subfile')))
- self.assertTrue(os.path.exists(os.path.join(dst_directory, 'subdir')))
+ self.assertTrue(os.path.exists(os.path.join(dst_directory, "subfile")))
+ self.assertTrue(os.path.exists(os.path.join(dst_directory, "subdir")))
self.assertFalse(os.path.exists(src_directory))
def test_disk_usage(self):
self.skip_real_fs()
- file_path = self.make_path('foo', 'bar')
+ file_path = self.make_path("foo", "bar")
self.fs.create_file(file_path, st_size=400)
- # root = self.os.path.splitdrive(file_path)[0] + self.fs.path_separator
disk_usage = shutil.disk_usage(file_path)
self.assertEqual(1000, disk_usage.total)
self.assertEqual(400, disk_usage.used)
@@ -359,14 +371,25 @@ class FakeShutilModuleTest(RealFsTestCase):
self.assertEqual((1000, 400, 600), disk_usage)
mount_point = self.create_mount_point()
- dir_path = self.os.path.join(mount_point, 'foo')
- file_path = self.os.path.join(dir_path, 'bar')
+ dir_path = self.os.path.join(mount_point, "foo")
+ file_path = self.os.path.join(dir_path, "bar")
self.fs.create_file(file_path, st_size=400)
disk_usage = shutil.disk_usage(dir_path)
self.assertEqual((500, 400, 100), disk_usage)
+ def test_disk_usage_with_path(self):
+ self.skip_real_fs()
+ file_path = self.make_path("foo", "bar")
+ self.fs.create_file(file_path, st_size=400)
+ path = Path(file_path)
+ disk_usage = shutil.disk_usage(path)
+ self.assertEqual(1000, disk_usage.total)
+ self.assertEqual(400, disk_usage.used)
+ self.assertEqual(600, disk_usage.free)
+ self.assertEqual((1000, 400, 600), disk_usage)
+
def create_mount_point(self):
- mount_point = 'M:' if self.is_windows_fs else '/mount'
+ mount_point = "M:" if self.is_windows_fs else "/mount"
self.fs.add_mount_point(mount_point, total_size=500)
return mount_point
@@ -381,9 +404,9 @@ class FakeCopyFileTest(RealFsTestCase):
super(FakeCopyFileTest, self).tearDown()
def test_common_case(self):
- src_file = self.make_path('xyzzy')
- dst_file = self.make_path('xyzzy_copy')
- contents = 'contents of file'
+ src_file = self.make_path("xyzzy")
+ dst_file = self.make_path("xyzzy_copy")
+ contents = "contents of file"
self.create_file(src_file, contents=contents)
self.assertTrue(os.path.exists(src_file))
self.assertFalse(os.path.exists(dst_file))
@@ -392,9 +415,9 @@ class FakeCopyFileTest(RealFsTestCase):
self.check_contents(dst_file, contents)
def test_raises_if_source_and_dest_are_the_same_file(self):
- src_file = self.make_path('xyzzy')
+ src_file = self.make_path("xyzzy")
dst_file = src_file
- contents = 'contents of file'
+ contents = "contents of file"
self.create_file(src_file, contents=contents)
self.assertTrue(os.path.exists(src_file))
with self.assertRaises(shutil.Error):
@@ -402,9 +425,9 @@ class FakeCopyFileTest(RealFsTestCase):
def test_raises_if_dest_is_a_symlink_to_src(self):
self.skip_if_symlink_not_supported()
- src_file = self.make_path('foo')
- dst_file = self.make_path('bar')
- contents = 'contents of file'
+ src_file = self.make_path("foo")
+ dst_file = self.make_path("bar")
+ contents = "contents of file"
self.create_file(src_file, contents=contents)
self.create_symlink(dst_file, src_file)
self.assertTrue(os.path.exists(src_file))
@@ -412,10 +435,10 @@ class FakeCopyFileTest(RealFsTestCase):
shutil.copyfile(src_file, dst_file)
def test_succeeds_if_dest_exists_and_is_writable(self):
- src_file = self.make_path('xyzzy')
- dst_file = self.make_path('xyzzy_copy')
- src_contents = 'contents of source file'
- dst_contents = 'contents of dest file'
+ src_file = self.make_path("xyzzy")
+ dst_file = self.make_path("xyzzy_copy")
+ src_contents = "contents of source file"
+ dst_contents = "contents of dest file"
self.create_file(src_file, contents=src_contents)
self.create_file(dst_file, contents=dst_contents)
self.assertTrue(os.path.exists(src_file))
@@ -425,10 +448,10 @@ class FakeCopyFileTest(RealFsTestCase):
self.check_contents(dst_file, src_contents)
def test_raises_if_dest_exists_and_is_not_writable(self):
- src_file = self.make_path('xyzzy')
- dst_file = self.make_path('xyzzy_copy')
- src_contents = 'contents of source file'
- dst_contents = 'contents of dest file'
+ src_file = self.make_path("xyzzy")
+ dst_file = self.make_path("xyzzy_copy")
+ src_contents = "contents of source file"
+ dst_contents = "contents of dest file"
self.create_file(src_file, contents=src_contents)
self.create_file(dst_file, contents=dst_contents)
os.chmod(dst_file, 0o400)
@@ -439,20 +462,20 @@ class FakeCopyFileTest(RealFsTestCase):
shutil.copyfile(src_file, dst_file)
self.assertTrue(self.os.path.exists(dst_file))
with self.open(dst_file) as f:
- self.assertEqual('contents of source file', f.read())
+ self.assertEqual("contents of source file", f.read())
else:
with self.assertRaises(OSError):
shutil.copyfile(src_file, dst_file)
os.chmod(dst_file, 0o666)
- @unittest.skipIf(is_windows, 'Posix specific behavior')
+ @unittest.skipIf(is_windows, "Posix specific behavior")
def test_raises_if_dest_dir_is_not_writable_under_posix(self):
self.check_posix_only()
- src_file = self.make_path('xyzzy')
- dst_dir = self.make_path('tmp', 'foo')
- dst_file = os.path.join(dst_dir, 'xyzzy')
- src_contents = 'contents of source file'
+ src_file = self.make_path("xyzzy")
+ dst_dir = self.make_path("tmp", "foo")
+ dst_file = os.path.join(dst_dir, "xyzzy")
+ src_contents = "contents of source file"
self.create_file(src_file, contents=src_contents)
self.create_dir(dst_dir)
os.chmod(dst_dir, 0o555)
@@ -467,18 +490,18 @@ class FakeCopyFileTest(RealFsTestCase):
self.check_contents(dst_file, src_contents)
def test_raises_if_src_doesnt_exist(self):
- src_file = self.make_path('xyzzy')
- dst_file = self.make_path('xyzzy_copy')
+ src_file = self.make_path("xyzzy")
+ dst_file = self.make_path("xyzzy_copy")
self.assertFalse(os.path.exists(src_file))
with self.assertRaises(OSError):
shutil.copyfile(src_file, dst_file)
- @unittest.skipIf(is_windows, 'Posix specific behavior')
+ @unittest.skipIf(is_windows, "Posix specific behavior")
def test_raises_if_src_not_readable(self):
self.check_posix_only()
- src_file = self.make_path('xyzzy')
- dst_file = self.make_path('xyzzy_copy')
- src_contents = 'contents of source file'
+ src_file = self.make_path("xyzzy")
+ dst_file = self.make_path("xyzzy_copy")
+ src_contents = "contents of source file"
self.create_file(src_file, contents=src_contents)
os.chmod(src_file, 0o000)
self.assertTrue(os.path.exists(src_file))
@@ -491,17 +514,17 @@ class FakeCopyFileTest(RealFsTestCase):
self.check_contents(dst_file, src_contents)
def test_raises_if_src_is_a_directory(self):
- src_file = self.make_path('xyzzy')
- dst_file = self.make_path('xyzzy_copy')
+ src_file = self.make_path("xyzzy")
+ dst_file = self.make_path("xyzzy_copy")
self.create_dir(src_file)
self.assertTrue(os.path.exists(src_file))
with self.assertRaises(OSError):
shutil.copyfile(src_file, dst_file)
def test_raises_if_dest_is_a_directory(self):
- src_file = self.make_path('xyzzy')
- dst_dir = self.make_path('tmp', 'foo')
- src_contents = 'contents of source file'
+ src_file = self.make_path("xyzzy")
+ dst_dir = self.make_path("tmp", "foo")
+ src_contents = "contents of source file"
self.create_file(src_file, contents=src_contents)
self.create_dir(dst_dir)
self.assertTrue(os.path.exists(src_file))
@@ -513,9 +536,9 @@ class FakeCopyFileTest(RealFsTestCase):
# regression test for #515
source_dir = tempfile.mkdtemp()
target_dir = tempfile.mkdtemp()
- filename = 'foo.pdf'
- with open(os.path.join(source_dir, filename), 'wb') as fp:
- fp.write(b'stub')
+ filename = "foo.pdf"
+ with open(os.path.join(source_dir, filename), "wb") as fp:
+ fp.write(b"stub")
shutil.move(source_dir, target_dir)
shutil.rmtree(target_dir)
@@ -526,5 +549,5 @@ class RealCopyFileTest(FakeCopyFileTest):
return True
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
diff --git a/pyfakefs/tests/fake_filesystem_test.py b/pyfakefs/tests/fake_filesystem_test.py
index f131d2f..696f8a8 100644
--- a/pyfakefs/tests/fake_filesystem_test.py
+++ b/pyfakefs/tests/fake_filesystem_test.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
# Copyright 2009 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,23 +20,32 @@ import os
import stat
import sys
import unittest
-
-from pyfakefs import fake_filesystem
-from pyfakefs.fake_filesystem import set_uid, set_gid, is_root, reset_ids
+from unittest.mock import patch
+
+from pyfakefs import fake_filesystem, fake_os, fake_open
+from pyfakefs.fake_filesystem import (
+ set_uid,
+ set_gid,
+ is_root,
+ reset_ids,
+ OSType,
+)
from pyfakefs.helpers import IS_WIN
from pyfakefs.tests.test_utils import TestCase, RealFsTestCase, time_mock
class FakeDirectoryUnitTest(TestCase):
def setUp(self):
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
+ self.os = fake_os.FakeOsModule(self.filesystem)
self.time = time_mock(10, 1)
self.time.start()
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
- self.os = fake_filesystem.FakeOsModule(self.filesystem)
self.fake_file = fake_filesystem.FakeFile(
- 'foobar', contents='dummy_file', filesystem=self.filesystem)
+ "foobar", contents="dummy_file", filesystem=self.filesystem
+ )
self.fake_dir = fake_filesystem.FakeDirectory(
- 'somedir', filesystem=self.filesystem)
+ "somedir", filesystem=self.filesystem
+ )
def tearDown(self):
self.time.stop()
@@ -46,40 +54,40 @@ class FakeDirectoryUnitTest(TestCase):
self.assertTrue(stat.S_IFREG & self.fake_file.st_mode)
self.assertTrue(stat.S_IFDIR & self.fake_dir.st_mode)
self.assertEqual({}, self.fake_dir.entries)
- self.assertEqual(12, self.fake_file.st_ctime)
def test_add_entry(self):
self.fake_dir.add_entry(self.fake_file)
- self.assertEqual({'foobar': self.fake_file},
- self.fake_dir.entries)
+ self.assertEqual({"foobar": self.fake_file}, self.fake_dir.entries)
def test_get_entry(self):
self.fake_dir.add_entry(self.fake_file)
- self.assertEqual(self.fake_file, self.fake_dir.get_entry('foobar'))
+ self.assertEqual(self.fake_file, self.fake_dir.get_entry("foobar"))
def test_path(self):
+ root_dir = self.filesystem.root_dir_name
self.filesystem.root.add_entry(self.fake_dir)
self.fake_dir.add_entry(self.fake_file)
- self.assertEqual('/somedir/foobar', self.fake_file.path)
- self.assertEqual('/somedir', self.fake_dir.path)
+ self.assertEqual(f"{root_dir}somedir/foobar", self.fake_file.path)
+ self.assertEqual(f"{root_dir}somedir", self.fake_dir.path)
def test_path_with_drive(self):
self.filesystem.is_windows_fs = True
- dir_path = 'C:/foo/bar/baz'
+ dir_path = "C:/foo/bar/baz"
self.filesystem.create_dir(dir_path)
dir_object = self.filesystem.get_object(dir_path)
self.assertEqual(dir_path, dir_object.path)
def test_path_after_chdir(self):
- dir_path = '/foo/bar/baz'
+ root_dir = self.filesystem.root_dir_name
+ dir_path = "/foo/bar/baz"
self.filesystem.create_dir(dir_path)
self.os.chdir(dir_path)
dir_object = self.filesystem.get_object(dir_path)
- self.assertEqual(dir_path, dir_object.path)
+ self.assertEqual(f"{root_dir}foo/bar/baz", dir_object.path)
def test_path_after_chdir_with_drive(self):
self.filesystem.is_windows_fs = True
- dir_path = 'C:/foo/bar/baz'
+ dir_path = "C:/foo/bar/baz"
self.filesystem.create_dir(dir_path)
self.os.chdir(dir_path)
dir_object = self.filesystem.get_object(dir_path)
@@ -87,10 +95,10 @@ class FakeDirectoryUnitTest(TestCase):
def test_remove_entry(self):
self.fake_dir.add_entry(self.fake_file)
- self.assertEqual(self.fake_file, self.fake_dir.get_entry('foobar'))
- self.fake_dir.remove_entry('foobar')
+ self.assertEqual(self.fake_file, self.fake_dir.get_entry("foobar"))
+ self.fake_dir.remove_entry("foobar")
with self.assertRaises(KeyError):
- self.fake_dir.get_entry('foobar')
+ self.fake_dir.get_entry("foobar")
def test_should_throw_if_set_size_is_not_integer(self):
with self.raises_os_error(errno.ENOSPC):
@@ -102,78 +110,94 @@ class FakeDirectoryUnitTest(TestCase):
def test_produce_empty_file_if_set_size_is_zero(self):
self.fake_file.size = 0
- self.assertEqual('', self.fake_file.contents)
+ self.assertEqual("", self.fake_file.contents)
def test_sets_content_empty_if_set_size_is_zero(self):
self.fake_file.size = 0
- self.assertEqual('', self.fake_file.contents)
+ self.assertEqual("", self.fake_file.contents)
def test_truncate_file_if_size_is_smaller_than_current_size(self):
self.fake_file.size = 6
- self.assertEqual('dummy_', self.fake_file.contents)
+ self.assertEqual("dummy_", self.fake_file.contents)
def test_leave_file_unchanged_if_size_is_equal_to_current_size(self):
self.fake_file.size = 10
- self.assertEqual('dummy_file', self.fake_file.contents)
+ self.assertEqual("dummy_file", self.fake_file.contents)
def test_set_contents_to_dir_raises(self):
# Regression test for #276
self.filesystem.is_windows_fs = True
with self.raises_os_error(errno.EISDIR):
- self.fake_dir.set_contents('a')
+ self.fake_dir.set_contents("a")
self.filesystem.is_windows_fs = False
with self.raises_os_error(errno.EISDIR):
- self.fake_dir.set_contents('a')
+ self.fake_dir.set_contents("a")
def test_pads_with_nullbytes_if_size_is_greater_than_current_size(self):
self.fake_file.size = 13
- self.assertEqual('dummy_file\0\0\0', self.fake_file.contents)
+ self.assertEqual("dummy_file\0\0\0", self.fake_file.contents)
def test_set_m_time(self):
- self.assertEqual(12, self.fake_file.st_mtime)
- self.fake_file.st_mtime = 13
- self.assertEqual(13, self.fake_file.st_mtime)
+ self.assertEqual(10, self.fake_file.st_mtime)
+ self.fake_file.st_mtime = 14
+ self.assertEqual(14, self.fake_file.st_mtime)
self.fake_file.st_mtime = 131
self.assertEqual(131, self.fake_file.st_mtime)
def test_file_inode(self):
- filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
- fake_os = fake_filesystem.FakeOsModule(filesystem)
- file_path = 'some_file1'
- filesystem.create_file(file_path, contents='contents here1')
- self.assertLess(0, fake_os.stat(file_path)[stat.ST_INO])
+ filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
+ fake_os_module = fake_os.FakeOsModule(filesystem)
+ file_path = "some_file1"
+ filesystem.create_file(file_path, contents="contents here1")
+ self.assertLess(0, fake_os_module.stat(file_path)[stat.ST_INO])
file_obj = filesystem.get_object(file_path)
file_obj.st_ino = 43
- self.assertEqual(43, fake_os.stat(file_path)[stat.ST_INO])
+ self.assertEqual(43, fake_os_module.stat(file_path)[stat.ST_INO])
def test_directory_inode(self):
- filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
- fake_os = fake_filesystem.FakeOsModule(filesystem)
- dirpath = 'testdir'
+ filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
+ fake_os_module = fake_os.FakeOsModule(filesystem)
+ dirpath = "testdir"
filesystem.create_dir(dirpath)
- self.assertLess(0, fake_os.stat(dirpath)[stat.ST_INO])
+ self.assertLess(0, fake_os_module.stat(dirpath)[stat.ST_INO])
dir_obj = filesystem.get_object(dirpath)
dir_obj.st_ino = 43
- self.assertEqual(43, fake_os.stat(dirpath)[stat.ST_INO])
+ self.assertEqual(43, fake_os_module.stat(dirpath)[stat.ST_INO])
+
+ def test_directory_size(self):
+ fs = fake_filesystem.FakeFilesystem(path_separator="/")
+ foo_dir = fs.create_dir("/foo")
+ fs.create_file("/foo/bar.txt", st_size=20)
+ bar_dir = fs.create_dir("/foo/bar/")
+ fs.create_file("/foo/bar/baz1.txt", st_size=30)
+ fs.create_file("/foo/bar/baz2.txt", st_size=40)
+ foo1_dir = fs.create_dir("/foo1")
+ fs.create_file("/foo1/bar.txt", st_size=50)
+ fs.create_file("/foo1/bar/baz/file", st_size=60)
+ self.assertEqual(90, foo_dir.size)
+ self.assertEqual(70, bar_dir.size)
+ self.assertEqual(110, foo1_dir.size)
+ self.assertEqual(200, fs.root_dir.size)
+ with self.raises_os_error(errno.EISDIR):
+ foo1_dir.size = 100
def test_ordered_dirs(self):
- filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
- filesystem.create_dir('/foo')
- filesystem.create_file('/foo/2')
- filesystem.create_file('/foo/4')
- filesystem.create_file('/foo/1')
- filesystem.create_file('/foo/3')
- fake_dir = filesystem.get_object('/foo')
- self.assertEqual(['2', '4', '1', '3'], fake_dir.ordered_dirs)
+ filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
+ filesystem.create_dir("/foo")
+ filesystem.create_file("/foo/2")
+ filesystem.create_file("/foo/4")
+ filesystem.create_file("/foo/1")
+ filesystem.create_file("/foo/3")
+ fake_dir = filesystem.get_object("/foo")
+ self.assertEqual(["2", "4", "1", "3"], fake_dir.ordered_dirs)
class SetLargeFileSizeTest(TestCase):
def setUp(self):
filesystem = fake_filesystem.FakeFilesystem()
- self.fake_file = fake_filesystem.FakeFile('foobar',
- filesystem=filesystem)
+ self.fake_file = fake_filesystem.FakeFile("foobar", filesystem=filesystem)
def test_should_throw_if_size_is_not_integer(self):
with self.raises_os_error(errno.ENOSPC):
@@ -191,85 +215,87 @@ class SetLargeFileSizeTest(TestCase):
class NormalizePathTest(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
- self.root_name = '/'
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
+ self.root_name = self.filesystem.root_dir_name
def test_empty_path_should_get_normalized_to_root_path(self):
- self.assertEqual(self.root_name, self.filesystem.absnormpath(''))
+ self.assertEqual(self.root_name, self.filesystem.absnormpath(""))
def test_root_path_remains_unchanged(self):
- self.assertEqual(self.root_name,
- self.filesystem.absnormpath(self.root_name))
+ self.assertEqual(self.root_name, self.filesystem.absnormpath(self.root_name))
def test_relative_path_forced_to_cwd(self):
- path = 'bar'
- self.filesystem.cwd = '/foo'
- self.assertEqual('/foo/bar', self.filesystem.absnormpath(path))
+ path = "bar"
+ self.filesystem.cwd = "/foo"
+ self.assertEqual("/foo/bar", self.filesystem.absnormpath(path))
def test_absolute_path_remains_unchanged(self):
- path = '/foo/bar'
- self.assertEqual(path, self.filesystem.absnormpath(path))
+ path = "foo/bar"
+ self.assertEqual(self.root_name + path, self.filesystem.absnormpath(path))
def test_dotted_path_is_normalized(self):
- path = '/foo/..'
- self.assertEqual('/', self.filesystem.absnormpath(path))
- path = 'foo/../bar'
- self.assertEqual('/bar', self.filesystem.absnormpath(path))
+ path = "/foo/.."
+ self.assertEqual(
+ self.filesystem.root_dir_name, self.filesystem.absnormpath(path)
+ )
+ path = "foo/../bar"
+ self.assertEqual(
+ f"{self.filesystem.root_dir_name}bar",
+ self.filesystem.absnormpath(path),
+ )
def test_dot_path_is_normalized(self):
- path = '.'
- self.assertEqual('/', self.filesystem.absnormpath(path))
+ path = "."
+ self.assertEqual(self.root_name, self.filesystem.absnormpath(path))
class GetPathComponentsTest(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
- self.root_name = '/'
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
+ self.root_name = "/"
def test_root_path_should_return_empty_list(self):
self.assertEqual([], self.filesystem._path_components(self.root_name))
def test_empty_path_should_return_empty_list(self):
- self.assertEqual([], self.filesystem._path_components(''))
+ self.assertEqual([], self.filesystem._path_components(""))
def test_relative_path_with_one_component_should_return_component(self):
- self.assertEqual(['foo'], self.filesystem._path_components('foo'))
+ self.assertEqual(["foo"], self.filesystem._path_components("foo"))
def test_absolute_path_with_one_component_should_return_component(self):
- self.assertEqual(['foo'], self.filesystem._path_components('/foo'))
+ self.assertEqual(["foo"], self.filesystem._path_components("/foo"))
def test_two_level_relative_path_should_return_components(self):
- self.assertEqual(['foo', 'bar'],
- self.filesystem._path_components('foo/bar'))
+ self.assertEqual(["foo", "bar"], self.filesystem._path_components("foo/bar"))
def test_two_level_absolute_path_should_return_components(self):
- self.assertEqual(['foo', 'bar'],
- self.filesystem._path_components('/foo/bar'))
+ self.assertEqual(["foo", "bar"], self.filesystem._path_components("/foo/bar"))
class FakeFilesystemUnitTest(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
- self.root_name = '/'
- self.fake_file = fake_filesystem.FakeFile(
- 'foobar', filesystem=self.filesystem)
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
+ self.root_name = self.filesystem.root_dir_name
+ self.fake_file = fake_filesystem.FakeFile("foobar", filesystem=self.filesystem)
self.fake_child = fake_filesystem.FakeDirectory(
- 'foobaz', filesystem=self.filesystem)
+ "foobaz", filesystem=self.filesystem
+ )
self.fake_grandchild = fake_filesystem.FakeDirectory(
- 'quux', filesystem=self.filesystem)
+ "quux", filesystem=self.filesystem
+ )
def test_new_filesystem(self):
- self.assertEqual('/', self.filesystem.path_separator)
+ self.assertEqual("/", self.filesystem.path_separator)
self.assertTrue(stat.S_IFDIR & self.filesystem.root.st_mode)
- self.assertEqual(self.root_name, self.filesystem.root.name)
- self.assertEqual({}, self.filesystem.root.entries)
+ self.assertEqual({}, self.filesystem.root_dir.entries)
def test_none_raises_type_error(self):
with self.assertRaises(TypeError):
self.filesystem.exists(None)
def test_empty_string_does_not_exist(self):
- self.assertFalse(self.filesystem.exists(''))
+ self.assertFalse(self.filesystem.exists(""))
def test_exists_root(self):
self.assertTrue(self.filesystem.exists(self.root_name))
@@ -280,17 +306,26 @@ class FakeFilesystemUnitTest(TestCase):
def test_not_exists_subpath_named_like_file_contents(self):
# Regression test for #219
file_path = "/foo/bar"
- self.filesystem.create_file(file_path, contents='baz')
+ self.filesystem.create_file(file_path, contents="baz")
self.assertFalse(self.filesystem.exists(file_path + "/baz"))
def test_get_root_object(self):
- self.assertEqual(self.filesystem.root,
- self.filesystem.get_object(self.root_name))
+ self.assertEqual(
+ self.filesystem.root_dir,
+ self.filesystem.get_object(self.root_name),
+ )
def test_add_object_to_root(self):
self.filesystem.add_object(self.root_name, self.fake_file)
- self.assertEqual({'foobar': self.fake_file},
- self.filesystem.root.entries)
+ self.assertEqual({"foobar": self.fake_file}, self.filesystem.root_dir.entries)
+
+ def test_windows_root_dir_name(self):
+ self.filesystem.is_windows_fs = True
+ self.assertEqual("C:/", self.filesystem.root_dir_name)
+ self.filesystem.cwd = "E:/foo"
+ self.assertEqual("E:/", self.filesystem.root_dir_name)
+ self.filesystem.cwd = "//foo/bar"
+ self.assertEqual("//foo/bar/", self.filesystem.root_dir_name)
def test_exists_added_file(self):
self.filesystem.add_object(self.root_name, self.fake_file)
@@ -298,46 +333,46 @@ class FakeFilesystemUnitTest(TestCase):
def test_exists_relative_path_posix(self):
self.filesystem.is_windows_fs = False
- self.filesystem.create_file('/a/b/file_one')
- self.filesystem.create_file('/a/c/file_two')
- self.assertTrue(self.filesystem.exists('a/b/../c/file_two'))
- self.assertTrue(self.filesystem.exists('/a/c/../b/file_one'))
- self.assertTrue(self.filesystem.exists('/a/c/../../a/b/file_one'))
- self.assertFalse(self.filesystem.exists('a/b/../z/d'))
- self.assertFalse(self.filesystem.exists('a/b/../z/../c/file_two'))
- self.filesystem.cwd = '/a/c'
- self.assertTrue(self.filesystem.exists('../b/file_one'))
- self.assertTrue(self.filesystem.exists('../../a/b/file_one'))
- self.assertTrue(self.filesystem.exists('../../a/b/../../a/c/file_two'))
- self.assertFalse(self.filesystem.exists('../z/file_one'))
- self.assertFalse(self.filesystem.exists('../z/../c/file_two'))
+ self.filesystem.create_file("/a/b/file_one")
+ self.filesystem.create_file("/a/c/file_two")
+ self.assertTrue(self.filesystem.exists("a/b/../c/file_two"))
+ self.assertTrue(self.filesystem.exists("/a/c/../b/file_one"))
+ self.assertTrue(self.filesystem.exists("/a/c/../../a/b/file_one"))
+ self.assertFalse(self.filesystem.exists("a/b/../z/d"))
+ self.assertFalse(self.filesystem.exists("a/b/../z/../c/file_two"))
+ self.filesystem.cwd = "/a/c"
+ self.assertTrue(self.filesystem.exists("../b/file_one"))
+ self.assertTrue(self.filesystem.exists("../../a/b/file_one"))
+ self.assertTrue(self.filesystem.exists("../../a/b/../../a/c/file_two"))
+ self.assertFalse(self.filesystem.exists("../z/file_one"))
+ self.assertFalse(self.filesystem.exists("../z/../c/file_two"))
def test_exists_relative_path_windows(self):
self.filesystem.is_windows_fs = True
self.filesystem.is_macos = False
- self.filesystem.create_file('/a/b/file_one')
- self.filesystem.create_file('/a/c/file_two')
- self.assertTrue(self.filesystem.exists('a/b/../c/file_two'))
- self.assertTrue(self.filesystem.exists('/a/c/../b/file_one'))
- self.assertTrue(self.filesystem.exists('/a/c/../../a/b/file_one'))
- self.assertFalse(self.filesystem.exists('a/b/../z/d'))
- self.assertTrue(self.filesystem.exists('a/b/../z/../c/file_two'))
- self.filesystem.cwd = '/a/c'
- self.assertTrue(self.filesystem.exists('../b/file_one'))
- self.assertTrue(self.filesystem.exists('../../a/b/file_one'))
- self.assertTrue(self.filesystem.exists('../../a/b/../../a/c/file_two'))
- self.assertFalse(self.filesystem.exists('../z/file_one'))
- self.assertTrue(self.filesystem.exists('../z/../c/file_two'))
+ self.filesystem.create_file("/a/b/file_one")
+ self.filesystem.create_file("/a/c/file_two")
+ self.assertTrue(self.filesystem.exists("a/b/../c/file_two"))
+ self.assertTrue(self.filesystem.exists("/a/c/../b/file_one"))
+ self.assertTrue(self.filesystem.exists("/a/c/../../a/b/file_one"))
+ self.assertFalse(self.filesystem.exists("a/b/../z/d"))
+ self.assertTrue(self.filesystem.exists("a/b/../z/../c/file_two"))
+ self.filesystem.cwd = "C:/a/c"
+ self.assertTrue(self.filesystem.exists("../b/file_one"))
+ self.assertTrue(self.filesystem.exists("../../a/b/file_one"))
+ self.assertTrue(self.filesystem.exists("../../a/b/../../a/c/file_two"))
+ self.assertFalse(self.filesystem.exists("../z/file_one"))
+ self.assertTrue(self.filesystem.exists("../z/../c/file_two"))
def test_get_object_from_root(self):
self.filesystem.add_object(self.root_name, self.fake_file)
- self.assertEqual(self.fake_file, self.filesystem.get_object('foobar'))
+ self.assertEqual(self.fake_file, self.filesystem.get_object("foobar"))
def test_get_nonexistent_object_from_root_error(self):
self.filesystem.add_object(self.root_name, self.fake_file)
- self.assertEqual(self.fake_file, self.filesystem.get_object('foobar'))
+ self.assertEqual(self.fake_file, self.filesystem.get_object("foobar"))
with self.raises_os_error(errno.ENOENT):
- self.filesystem.get_object('some_bogus_filename')
+ self.filesystem.get_object("some_bogus_filename")
def test_remove_object_from_root(self):
self.filesystem.add_object(self.root_name, self.fake_file)
@@ -347,7 +382,7 @@ class FakeFilesystemUnitTest(TestCase):
def test_remove_nonexisten_object_from_root_error(self):
with self.raises_os_error(errno.ENOENT):
- self.filesystem.remove_object('some_bogus_filename')
+ self.filesystem.remove_object("some_bogus_filename")
def test_exists_removed_file(self):
self.filesystem.add_object(self.root_name, self.fake_file)
@@ -359,11 +394,12 @@ class FakeFilesystemUnitTest(TestCase):
self.filesystem.add_object(self.fake_child.name, self.fake_file)
self.assertEqual(
{self.fake_file.name: self.fake_file},
- self.filesystem.root.get_entry(self.fake_child.name).entries)
+ self.filesystem.root_dir.get_entry(self.fake_child.name).entries,
+ )
def test_add_object_to_regular_file_error_posix(self):
self.filesystem.is_windows_fs = False
- self.filesystem.add_object(self.root_name, self.fake_file)
+ self.filesystem.add_object(self.filesystem.root_dir_name, self.fake_file)
with self.raises_os_error(errno.ENOTDIR):
self.filesystem.add_object(self.fake_file.name, self.fake_file)
@@ -376,30 +412,33 @@ class FakeFilesystemUnitTest(TestCase):
def test_exists_file_added_to_child(self):
self.filesystem.add_object(self.root_name, self.fake_child)
self.filesystem.add_object(self.fake_child.name, self.fake_file)
- path = self.filesystem.joinpaths(self.fake_child.name,
- self.fake_file.name)
+ path = self.filesystem.joinpaths(self.fake_child.name, self.fake_file.name)
self.assertTrue(self.filesystem.exists(path))
def test_get_object_from_child(self):
self.filesystem.add_object(self.root_name, self.fake_child)
self.filesystem.add_object(self.fake_child.name, self.fake_file)
- self.assertEqual(self.fake_file,
- self.filesystem.get_object(
- self.filesystem.joinpaths(self.fake_child.name,
- self.fake_file.name)))
+ self.assertEqual(
+ self.fake_file,
+ self.filesystem.get_object(
+ self.filesystem.joinpaths(self.fake_child.name, self.fake_file.name)
+ ),
+ )
def test_get_nonexistent_object_from_child_error(self):
self.filesystem.add_object(self.root_name, self.fake_child)
self.filesystem.add_object(self.fake_child.name, self.fake_file)
with self.raises_os_error(errno.ENOENT):
- self.filesystem.get_object(self.filesystem.joinpaths(
- self.fake_child.name, 'some_bogus_filename'))
+ self.filesystem.get_object(
+ self.filesystem.joinpaths(self.fake_child.name, "some_bogus_filename")
+ )
def test_remove_object_from_child(self):
self.filesystem.add_object(self.root_name, self.fake_child)
self.filesystem.add_object(self.fake_child.name, self.fake_file)
- target_path = self.filesystem.joinpaths(self.fake_child.name,
- self.fake_file.name)
+ target_path = self.filesystem.joinpaths(
+ self.fake_child.name, self.fake_file.name
+ )
self.filesystem.remove_object(target_path)
with self.raises_os_error(errno.ENOENT):
self.filesystem.get_object(target_path)
@@ -408,22 +447,23 @@ class FakeFilesystemUnitTest(TestCase):
self.filesystem.add_object(self.root_name, self.fake_child)
with self.raises_os_error(errno.ENOENT):
self.filesystem.remove_object(
- self.filesystem.joinpaths(self.fake_child.name,
- 'some_bogus_filename'))
+ self.filesystem.joinpaths(self.fake_child.name, "some_bogus_filename")
+ )
def test_remove_object_from_non_directory_error(self):
self.filesystem.add_object(self.root_name, self.fake_file)
with self.raises_os_error(errno.ENOTDIR):
self.filesystem.remove_object(
self.filesystem.joinpaths(
- '%s' % self.fake_file.name,
- 'file_does_not_matter_since_parent_not_a_directory'))
+ "%s" % self.fake_file.name,
+ "file_does_not_matter_since_parent_not_a_directory",
+ )
+ )
def test_exists_file_removed_from_child(self):
self.filesystem.add_object(self.root_name, self.fake_child)
self.filesystem.add_object(self.fake_child.name, self.fake_file)
- path = self.filesystem.joinpaths(self.fake_child.name,
- self.fake_file.name)
+ path = self.filesystem.joinpaths(self.fake_child.name, self.fake_file.name)
self.filesystem.remove_object(path)
self.assertFalse(self.filesystem.exists(path))
@@ -431,14 +471,15 @@ class FakeFilesystemUnitTest(TestCase):
self.filesystem.add_object(self.root_name, self.fake_child)
self.filesystem.add_object(self.fake_child.name, self.fake_grandchild)
grandchild_directory = self.filesystem.joinpaths(
- self.fake_child.name, self.fake_grandchild.name)
+ self.fake_child.name, self.fake_grandchild.name
+ )
grandchild_file = self.filesystem.joinpaths(
- grandchild_directory, self.fake_file.name)
+ grandchild_directory, self.fake_file.name
+ )
with self.assertRaises(OSError):
self.filesystem.get_object(grandchild_file)
self.filesystem.add_object(grandchild_directory, self.fake_file)
- self.assertEqual(self.fake_file,
- self.filesystem.get_object(grandchild_file))
+ self.assertEqual(self.fake_file, self.filesystem.get_object(grandchild_file))
self.assertTrue(self.filesystem.exists(grandchild_file))
self.filesystem.remove_object(grandchild_file)
with self.assertRaises(OSError):
@@ -446,43 +487,43 @@ class FakeFilesystemUnitTest(TestCase):
self.assertFalse(self.filesystem.exists(grandchild_file))
def test_create_directory_in_root_directory(self):
- path = 'foo'
+ path = "foo"
self.filesystem.create_dir(path)
new_dir = self.filesystem.get_object(path)
self.assertEqual(os.path.basename(path), new_dir.name)
self.assertTrue(stat.S_IFDIR & new_dir.st_mode)
def test_create_directory_in_root_directory_already_exists_error(self):
- path = 'foo'
+ path = "foo"
self.filesystem.create_dir(path)
with self.raises_os_error(errno.EEXIST):
self.filesystem.create_dir(path)
def test_create_directory(self):
- path = 'foo/bar/baz'
+ path = "foo/bar/baz"
self.filesystem.create_dir(path)
new_dir = self.filesystem.get_object(path)
self.assertEqual(os.path.basename(path), new_dir.name)
self.assertTrue(stat.S_IFDIR & new_dir.st_mode)
# Create second directory to make sure first is OK.
- path = '%s/quux' % path
+ path = "%s/quux" % path
self.filesystem.create_dir(path)
new_dir = self.filesystem.get_object(path)
self.assertEqual(os.path.basename(path), new_dir.name)
self.assertTrue(stat.S_IFDIR & new_dir.st_mode)
def test_create_directory_already_exists_error(self):
- path = 'foo/bar/baz'
+ path = "foo/bar/baz"
self.filesystem.create_dir(path)
with self.raises_os_error(errno.EEXIST):
self.filesystem.create_dir(path)
def test_create_file_in_read_only_directory_raises_in_posix(self):
self.filesystem.is_windows_fs = False
- dir_path = '/foo/bar'
+ dir_path = "/foo/bar"
self.filesystem.create_dir(dir_path, perm_bits=0o555)
- file_path = dir_path + '/baz'
+ file_path = dir_path + "/baz"
if not is_root():
with self.raises_os_error(errno.EACCES):
@@ -493,24 +534,24 @@ class FakeFilesystemUnitTest(TestCase):
def test_create_file_in_read_only_directory_possible_in_windows(self):
self.filesystem.is_windows_fs = True
- dir_path = 'C:/foo/bar'
+ dir_path = "C:/foo/bar"
self.filesystem.create_dir(dir_path, perm_bits=0o555)
- file_path = dir_path + '/baz'
+ file_path = dir_path + "/baz"
self.filesystem.create_file(file_path)
self.assertTrue(self.filesystem.exists(file_path))
def test_create_file_in_current_directory(self):
- path = 'foo'
- contents = 'dummy data'
+ path = "foo"
+ contents = "dummy data"
self.filesystem.create_file(path, contents=contents)
self.assertTrue(self.filesystem.exists(path))
self.assertFalse(self.filesystem.exists(os.path.dirname(path)))
- path = './%s' % path
+ path = "./%s" % path
self.assertTrue(self.filesystem.exists(os.path.dirname(path)))
def test_create_file_in_root_directory(self):
- path = '/foo'
- contents = 'dummy data'
+ path = "/foo"
+ contents = "dummy data"
self.filesystem.create_file(path, contents=contents)
new_file = self.filesystem.get_object(path)
self.assertTrue(self.filesystem.exists(path))
@@ -520,21 +561,21 @@ class FakeFilesystemUnitTest(TestCase):
self.assertEqual(contents, new_file.contents)
def test_create_file_with_size_but_no_content_creates_large_file(self):
- path = 'large_foo_bar'
+ path = "large_foo_bar"
self.filesystem.create_file(path, st_size=100000000)
new_file = self.filesystem.get_object(path)
self.assertEqual(None, new_file.contents)
self.assertEqual(100000000, new_file.st_size)
def test_create_file_in_root_directory_already_exists_error(self):
- path = 'foo'
+ path = "foo"
self.filesystem.create_file(path)
with self.raises_os_error(errno.EEXIST):
self.filesystem.create_file(path)
def test_create_file(self):
- path = 'foo/bar/baz'
- retval = self.filesystem.create_file(path, contents='dummy_data')
+ path = "foo/bar/baz"
+ retval = self.filesystem.create_file(path, contents="dummy_data")
self.assertTrue(self.filesystem.exists(path))
self.assertTrue(self.filesystem.exists(os.path.dirname(path)))
new_file = self.filesystem.get_object(path)
@@ -548,7 +589,7 @@ class FakeFilesystemUnitTest(TestCase):
self.assertEqual(new_file, retval)
def test_create_file_with_changed_ids(self):
- path = 'foo/bar/baz'
+ path = "foo/bar/baz"
set_uid(42)
set_gid(2)
self.filesystem.create_file(path)
@@ -560,25 +601,25 @@ class FakeFilesystemUnitTest(TestCase):
def test_empty_file_created_for_none_contents(self):
fake_open = fake_filesystem.FakeFileOpen(self.filesystem)
- path = 'foo/bar/baz'
+ path = "foo/bar/baz"
self.filesystem.create_file(path, contents=None)
with fake_open(path) as f:
- self.assertEqual('', f.read())
+ self.assertEqual("", f.read())
def test_create_file_with_incorrect_mode_type(self):
with self.assertRaises(TypeError):
- self.filesystem.create_file('foo', 'bar')
+ self.filesystem.create_file("foo", "bar")
def test_create_file_already_exists_error(self):
- path = 'foo/bar/baz'
- self.filesystem.create_file(path, contents='dummy_data')
+ path = "foo/bar/baz"
+ self.filesystem.create_file(path, contents="dummy_data")
with self.raises_os_error(errno.EEXIST):
self.filesystem.create_file(path)
def test_create_link(self):
- path = 'foo/bar/baz'
- target_path = 'foo/bar/quux'
- new_file = self.filesystem.create_symlink(path, 'quux')
+ path = "foo/bar/baz"
+ target_path = "foo/bar/quux"
+ new_file = self.filesystem.create_symlink(path, "quux")
# Neither the path nor the final target exists before we actually
# write to one of them, even though the link appears in the file
# system.
@@ -592,22 +633,22 @@ class FakeFilesystemUnitTest(TestCase):
self.assertTrue(self.filesystem.exists(target_path))
def test_resolve_object(self):
- target_path = 'dir/target'
- target_contents = '0123456789ABCDEF'
- link_name = 'x'
- self.filesystem.create_dir('dir')
- self.filesystem.create_file('dir/target', contents=target_contents)
+ target_path = "dir/target"
+ target_contents = "0123456789ABCDEF"
+ link_name = "x"
+ self.filesystem.create_dir("dir")
+ self.filesystem.create_file("dir/target", contents=target_contents)
self.filesystem.create_symlink(link_name, target_path)
obj = self.filesystem.resolve(link_name)
- self.assertEqual('target', obj.name)
+ self.assertEqual("target", obj.name)
self.assertEqual(target_contents, obj.contents)
def check_lresolve_object(self):
- target_path = 'dir/target'
- target_contents = '0123456789ABCDEF'
- link_name = 'x'
- self.filesystem.create_dir('dir')
- self.filesystem.create_file('dir/target', contents=target_contents)
+ target_path = "dir/target"
+ target_contents = "0123456789ABCDEF"
+ link_name = "x"
+ self.filesystem.create_dir("dir")
+ self.filesystem.create_file("dir/target", contents=target_contents)
self.filesystem.create_symlink(link_name, target_path)
obj = self.filesystem.lresolve(link_name)
self.assertEqual(link_name, obj.name)
@@ -622,11 +663,11 @@ class FakeFilesystemUnitTest(TestCase):
self.check_lresolve_object()
def check_directory_access_on_file(self, error_subtype):
- self.filesystem.create_file('not_a_dir')
+ self.filesystem.create_file("not_a_dir")
with self.raises_os_error(error_subtype):
- self.filesystem.resolve('not_a_dir/foo')
+ self.filesystem.resolve("not_a_dir/foo")
with self.raises_os_error(error_subtype):
- self.filesystem.lresolve('not_a_dir/foo/bar')
+ self.filesystem.lresolve("not_a_dir/foo/bar")
def test_directory_access_on_file_windows(self):
self.filesystem.is_windows_fs = True
@@ -639,6 +680,7 @@ class FakeFilesystemUnitTest(TestCase):
def test_pickle_fs(self):
"""Regression test for #445"""
import pickle
+
self.filesystem.open_files = []
p = pickle.dumps(self.filesystem)
fs = pickle.loads(p)
@@ -648,66 +690,68 @@ class FakeFilesystemUnitTest(TestCase):
class CaseInsensitiveFakeFilesystemTest(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
self.filesystem.is_case_sensitive = False
- self.os = fake_filesystem.FakeOsModule(self.filesystem)
+ self.os = fake_os.FakeOsModule(self.filesystem)
self.path = self.os.path
def test_get_object(self):
- self.filesystem.create_dir('/foo/bar')
- self.filesystem.create_file('/foo/bar/baz')
- self.assertTrue(self.filesystem.get_object('/Foo/Bar/Baz'))
+ self.filesystem.create_dir("/foo/bar")
+ self.filesystem.create_file("/foo/bar/baz")
+ self.assertTrue(self.filesystem.get_object("/Foo/Bar/Baz"))
def test_remove_object(self):
- self.filesystem.create_dir('/foo/bar')
- self.filesystem.create_file('/foo/bar/baz')
- self.filesystem.remove_object('/Foo/Bar/Baz')
- self.assertFalse(self.filesystem.exists('/foo/bar/baz'))
+ self.filesystem.create_dir("/foo/bar")
+ self.filesystem.create_file("/foo/bar/baz")
+ self.filesystem.remove_object("/Foo/Bar/Baz")
+ self.assertFalse(self.filesystem.exists("/foo/bar/baz"))
def test_exists(self):
- self.filesystem.create_dir('/Foo/Bar')
- self.assertTrue(self.filesystem.exists('/Foo/Bar'))
- self.assertTrue(self.filesystem.exists('/foo/bar'))
+ self.filesystem.create_dir("/Foo/Bar")
+ self.assertTrue(self.filesystem.exists("/Foo/Bar"))
+ self.assertTrue(self.filesystem.exists("/foo/bar"))
- self.filesystem.create_file('/foo/Bar/baz')
- self.assertTrue(self.filesystem.exists('/Foo/bar/BAZ'))
- self.assertTrue(self.filesystem.exists('/foo/bar/baz'))
+ self.filesystem.create_file("/foo/Bar/baz")
+ self.assertTrue(self.filesystem.exists("/Foo/bar/BAZ"))
+ self.assertTrue(self.filesystem.exists("/foo/bar/baz"))
def test_create_directory_with_different_case_root(self):
- self.filesystem.create_dir('/Foo/Bar')
- self.filesystem.create_dir('/foo/bar/baz')
- dir1 = self.filesystem.get_object('/Foo/Bar')
- dir2 = self.filesystem.get_object('/foo/bar')
+ self.filesystem.create_dir("/Foo/Bar")
+ self.filesystem.create_dir("/foo/bar/baz")
+ dir1 = self.filesystem.get_object("/Foo/Bar")
+ dir2 = self.filesystem.get_object("/foo/bar")
self.assertEqual(dir1, dir2)
def test_create_file_with_different_case_dir(self):
- self.filesystem.create_dir('/Foo/Bar')
- self.filesystem.create_file('/foo/bar/baz')
- dir1 = self.filesystem.get_object('/Foo/Bar')
- dir2 = self.filesystem.get_object('/foo/bar')
+ self.filesystem.create_dir("/Foo/Bar")
+ self.filesystem.create_file("/foo/bar/baz")
+ dir1 = self.filesystem.get_object("/Foo/Bar")
+ dir2 = self.filesystem.get_object("/foo/bar")
self.assertEqual(dir1, dir2)
def test_resolve_path(self):
- self.filesystem.create_dir('/foo/baz')
- self.filesystem.create_symlink('/Foo/Bar', './baz/bip')
- self.assertEqual('/foo/baz/bip',
- self.filesystem.resolve_path('/foo/bar'))
+ self.filesystem.create_dir("/foo/baz")
+ self.filesystem.create_symlink("/Foo/Bar", "./baz/bip")
+ self.assertEqual(
+ f"{self.filesystem.root_dir_name}foo/baz/bip",
+ self.filesystem.resolve_path("/foo/bar"),
+ )
def test_isdir_isfile(self):
- self.filesystem.create_file('foo/bar')
- self.assertTrue(self.path.isdir('Foo'))
- self.assertFalse(self.path.isfile('Foo'))
- self.assertTrue(self.path.isfile('Foo/Bar'))
- self.assertFalse(self.path.isdir('Foo/Bar'))
+ self.filesystem.create_file("foo/bar")
+ self.assertTrue(self.path.isdir("Foo"))
+ self.assertFalse(self.path.isfile("Foo"))
+ self.assertTrue(self.path.isfile("Foo/Bar"))
+ self.assertFalse(self.path.isdir("Foo/Bar"))
def test_getsize(self):
- file_path = 'foo/bar/baz'
- self.filesystem.create_file(file_path, contents='1234567')
- self.assertEqual(7, self.path.getsize('FOO/BAR/BAZ'))
+ file_path = "foo/bar/baz"
+ self.filesystem.create_file(file_path, contents="1234567")
+ self.assertEqual(7, self.path.getsize("FOO/BAR/BAZ"))
def test_getsize_with_looping_symlink(self):
self.filesystem.is_windows_fs = False
- dir_path = '/foo/bar'
+ dir_path = "/foo/bar"
self.filesystem.create_dir(dir_path)
link_path = dir_path + "/link"
link_target = link_path + "/link"
@@ -716,118 +760,117 @@ class CaseInsensitiveFakeFilesystemTest(TestCase):
self.os.path.getsize(link_path)
def test_get_mtime(self):
- test_file = self.filesystem.create_file('foo/bar1.txt')
+ test_file = self.filesystem.create_file("foo/bar1.txt")
test_file.st_mtime = 24
- self.assertEqual(24, self.path.getmtime('Foo/Bar1.TXT'))
+ self.assertEqual(24, self.path.getmtime("Foo/Bar1.TXT"))
def test_get_object_with_file_size(self):
- self.filesystem.create_file('/Foo/Bar', st_size=10)
- self.assertTrue(self.filesystem.get_object('/foo/bar'))
+ self.filesystem.create_file("/Foo/Bar", st_size=10)
+ self.assertTrue(self.filesystem.get_object("/foo/bar"))
class CaseSensitiveFakeFilesystemTest(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
self.filesystem.is_case_sensitive = True
- self.os = fake_filesystem.FakeOsModule(self.filesystem)
+ self.os = fake_os.FakeOsModule(self.filesystem)
self.path = self.os.path
def test_get_object(self):
- self.filesystem.create_dir('/foo/bar')
- self.filesystem.create_file('/foo/bar/baz')
+ self.filesystem.create_dir("/foo/bar")
+ self.filesystem.create_file("/foo/bar/baz")
with self.assertRaises(OSError):
- self.filesystem.get_object('/Foo/Bar/Baz')
+ self.filesystem.get_object("/Foo/Bar/Baz")
def test_remove_object(self):
- self.filesystem.create_dir('/foo/bar')
- self.filesystem.create_file('/foo/bar/baz')
+ self.filesystem.create_dir("/foo/bar")
+ self.filesystem.create_file("/foo/bar/baz")
with self.assertRaises(OSError):
- self.filesystem.remove_object('/Foo/Bar/Baz')
- self.assertTrue(self.filesystem.exists('/foo/bar/baz'))
+ self.filesystem.remove_object("/Foo/Bar/Baz")
+ self.assertTrue(self.filesystem.exists("/foo/bar/baz"))
def test_exists(self):
- self.filesystem.create_dir('/Foo/Bar')
- self.assertTrue(self.filesystem.exists('/Foo/Bar'))
- self.assertFalse(self.filesystem.exists('/foo/bar'))
+ self.filesystem.create_dir("/Foo/Bar")
+ self.assertTrue(self.filesystem.exists("/Foo/Bar"))
+ self.assertFalse(self.filesystem.exists("/foo/bar"))
- self.filesystem.create_file('/foo/Bar/baz')
- self.assertFalse(self.filesystem.exists('/Foo/bar/BAZ'))
- self.assertFalse(self.filesystem.exists('/foo/bar/baz'))
+ self.filesystem.create_file("/foo/Bar/baz")
+ self.assertFalse(self.filesystem.exists("/Foo/bar/BAZ"))
+ self.assertFalse(self.filesystem.exists("/foo/bar/baz"))
def test_create_directory_with_different_case_root(self):
- self.filesystem.create_dir('/Foo/Bar')
- self.filesystem.create_dir('/foo/bar/baz')
- dir1 = self.filesystem.get_object('/Foo/Bar')
- dir2 = self.filesystem.get_object('/foo/bar')
+ self.filesystem.create_dir("/Foo/Bar")
+ self.filesystem.create_dir("/foo/bar/baz")
+ dir1 = self.filesystem.get_object("/Foo/Bar")
+ dir2 = self.filesystem.get_object("/foo/bar")
self.assertNotEqual(dir1, dir2)
def test_create_file_with_different_case_dir(self):
- self.filesystem.create_dir('/Foo/Bar')
- self.filesystem.create_file('/foo/bar/baz')
- dir1 = self.filesystem.get_object('/Foo/Bar')
- dir2 = self.filesystem.get_object('/foo/bar')
+ self.filesystem.create_dir("/Foo/Bar")
+ self.filesystem.create_file("/foo/bar/baz")
+ dir1 = self.filesystem.get_object("/Foo/Bar")
+ dir2 = self.filesystem.get_object("/foo/bar")
self.assertNotEqual(dir1, dir2)
def test_isdir_isfile(self):
- self.filesystem.create_file('foo/bar')
- self.assertFalse(self.path.isdir('Foo'))
- self.assertFalse(self.path.isfile('Foo'))
- self.assertFalse(self.path.isfile('Foo/Bar'))
- self.assertFalse(self.path.isdir('Foo/Bar'))
+ self.filesystem.create_file("foo/bar")
+ self.assertFalse(self.path.isdir("Foo"))
+ self.assertFalse(self.path.isfile("Foo"))
+ self.assertFalse(self.path.isfile("Foo/Bar"))
+ self.assertFalse(self.path.isdir("Foo/Bar"))
def test_getsize(self):
- file_path = 'foo/bar/baz'
- self.filesystem.create_file(file_path, contents='1234567')
+ file_path = "foo/bar/baz"
+ self.filesystem.create_file(file_path, contents="1234567")
with self.assertRaises(os.error):
- self.path.getsize('FOO/BAR/BAZ')
+ self.path.getsize("FOO/BAR/BAZ")
def test_get_mtime(self):
- test_file = self.filesystem.create_file('foo/bar1.txt')
+ test_file = self.filesystem.create_file("foo/bar1.txt")
test_file.st_mtime = 24
with self.raises_os_error(errno.ENOENT):
- self.path.getmtime('Foo/Bar1.TXT')
+ self.path.getmtime("Foo/Bar1.TXT")
class OsPathInjectionRegressionTest(TestCase):
"""Test faking os.path before calling os.walk.
- Found when investigating a problem with
- gws/tools/labrat/rat_utils_unittest, which was faking out os.path
- before calling os.walk.
- """
+ Found when investigating a problem with
+ gws/tools/labrat/rat_utils_unittest, which was faking out os.path
+ before calling os.walk.
+ """
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
self.os_path = os.path
# The bug was that when os.path gets faked, the FakePathModule doesn't
# get called in self.os.walk(). FakePathModule now insists that it is
# created as part of FakeOsModule.
- self.os = fake_filesystem.FakeOsModule(self.filesystem)
+ self.os = fake_os.FakeOsModule(self.filesystem)
def tearDown(self):
os.path = self.os_path
def test_create_top_level_directory(self):
- top_level_dir = '/x'
+ top_level_dir = "/x"
self.assertFalse(self.filesystem.exists(top_level_dir))
self.filesystem.create_dir(top_level_dir)
- self.assertTrue(self.filesystem.exists('/'))
+ self.assertTrue(self.filesystem.exists("/"))
self.assertTrue(self.filesystem.exists(top_level_dir))
- self.filesystem.create_dir('%s/po' % top_level_dir)
- self.filesystem.create_file('%s/po/control' % top_level_dir)
- self.filesystem.create_file('%s/po/experiment' % top_level_dir)
- self.filesystem.create_dir('%s/gv' % top_level_dir)
- self.filesystem.create_file('%s/gv/control' % top_level_dir)
+ self.filesystem.create_dir("%s/po" % top_level_dir)
+ self.filesystem.create_file("%s/po/control" % top_level_dir)
+ self.filesystem.create_file("%s/po/experiment" % top_level_dir)
+ self.filesystem.create_dir("%s/gv" % top_level_dir)
+ self.filesystem.create_file("%s/gv/control" % top_level_dir)
expected = [
- ('/', ['x'], []),
- ('/x', ['gv', 'po'], []),
- ('/x/gv', [], ['control']),
- ('/x/po', [], ['control', 'experiment']),
+ ("/", ["x"], []),
+ ("/x", ["gv", "po"], []),
+ ("/x/gv", [], ["control"]),
+ ("/x/po", [], ["control", "experiment"]),
]
# as the result is unsorted, we have to check against sorted results
- result = sorted([step for step in self.os.walk('/')],
- key=lambda l: l[0])
+ result = sorted([step for step in self.os.walk("/")], key=lambda v: v[0])
self.assertEqual(len(expected), len(result))
for entry, expected_entry in zip(result, expected):
self.assertEqual(expected_entry[0], entry[0])
@@ -837,19 +880,19 @@ class OsPathInjectionRegressionTest(TestCase):
class FakePathModuleTest(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='!')
- self.os = fake_filesystem.FakeOsModule(self.filesystem)
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="!")
+ self.os = fake_os.FakeOsModule(self.filesystem)
self.path = self.os.path
def check_abspath(self, is_windows):
# the implementation differs in Windows and Posix, so test both
self.filesystem.is_windows_fs = is_windows
- filename = 'foo'
- abspath = '!%s' % filename
+ filename = "foo"
+ abspath = self.filesystem.root_dir_name + filename
self.filesystem.create_file(abspath)
self.assertEqual(abspath, self.path.abspath(abspath))
self.assertEqual(abspath, self.path.abspath(filename))
- self.assertEqual(abspath, self.path.abspath('..!%s' % filename))
+ self.assertEqual(abspath, self.path.abspath("..!%s" % filename))
def test_abspath_windows(self):
self.check_abspath(is_windows=True)
@@ -861,12 +904,12 @@ class FakePathModuleTest(TestCase):
def check_abspath_bytes(self, is_windows):
"""abspath should return a consistent representation of a file."""
self.filesystem.is_windows_fs = is_windows
- filename = b'foo'
- abspath = b'!' + filename
+ filename = b"foo"
+ abspath = self.filesystem.root_dir_name.encode() + filename
self.filesystem.create_file(abspath)
self.assertEqual(abspath, self.path.abspath(abspath))
self.assertEqual(abspath, self.path.abspath(filename))
- self.assertEqual(abspath, self.path.abspath(b'..!' + filename))
+ self.assertEqual(abspath, self.path.abspath(b"..!" + filename))
def test_abspath_bytes_windows(self):
self.check_abspath_bytes(is_windows=True)
@@ -881,305 +924,330 @@ class FakePathModuleTest(TestCase):
This test is distinct from the basic functionality test because
fake_filesystem has historically been based in !.
"""
- filename = '!foo!bar!baz'
+ filename = "!foo!bar!baz"
file_components = filename.split(self.path.sep)
- basedir = '!%s' % (file_components[0],)
+ root_name = self.filesystem.root_dir_name
+ basedir = f"{root_name}{file_components[0]}"
self.filesystem.create_file(filename)
self.os.chdir(basedir)
self.assertEqual(basedir, self.path.abspath(self.path.curdir))
- self.assertEqual('!', self.path.abspath('..'))
- self.assertEqual(self.path.join(basedir, file_components[1]),
- self.path.abspath(file_components[1]))
+ self.assertEqual(root_name, self.path.abspath(".."))
+ self.assertEqual(
+ self.path.join(basedir, file_components[1]),
+ self.path.abspath(file_components[1]),
+ )
def test_abs_path_with_drive_component(self):
self.filesystem.is_windows_fs = True
- self.filesystem.cwd = 'C:!foo'
- self.assertEqual('C:!foo!bar', self.path.abspath('bar'))
- self.assertEqual('C:!foo!bar', self.path.abspath('C:bar'))
- self.assertEqual('C:!foo!bar', self.path.abspath('!foo!bar'))
+ self.filesystem.cwd = "C:!foo"
+ self.assertEqual("C:!foo!bar", self.path.abspath("bar"))
+ self.assertEqual("C:!foo!bar", self.path.abspath("C:bar"))
+ self.assertEqual("C:!foo!bar", self.path.abspath("!foo!bar"))
def test_isabs_with_drive_component(self):
self.filesystem.is_windows_fs = False
- self.assertFalse(self.path.isabs('C:!foo'))
- self.assertFalse(self.path.isabs(b'C:!foo'))
- self.assertTrue(self.path.isabs('!'))
- self.assertTrue(self.path.isabs(b'!'))
+ self.assertFalse(self.path.isabs("C:!foo"))
+ self.assertFalse(self.path.isabs(b"C:!foo"))
+ self.assertTrue(self.path.isabs("!"))
+ self.assertTrue(self.path.isabs(b"!"))
self.filesystem.is_windows_fs = True
- self.assertTrue(self.path.isabs('C:!foo'))
- self.assertTrue(self.path.isabs(b'C:!foo'))
- self.assertTrue(self.path.isabs('!'))
- self.assertTrue(self.path.isabs(b'!'))
+ self.assertTrue(self.path.isabs("C:!foo"))
+ self.assertTrue(self.path.isabs(b"C:!foo"))
+ self.assertTrue(self.path.isabs("!"))
+ self.assertTrue(self.path.isabs(b"!"))
def test_relpath(self):
- path_foo = '!path!to!foo'
- path_bar = '!path!to!bar'
- path_other = '!some!where!else'
+ path_foo = "!path!to!foo"
+ path_bar = "!path!to!bar"
+ path_other = "!some!where!else"
with self.assertRaises(ValueError):
self.path.relpath(None)
with self.assertRaises(ValueError):
- self.path.relpath('')
- self.assertEqual('path!to!foo', self.path.relpath(path_foo))
- self.assertEqual('..!foo',
- self.path.relpath(path_foo, path_bar))
- self.assertEqual('..!..!..%s' % path_other,
- self.path.relpath(path_other, path_bar))
- self.assertEqual('.',
- self.path.relpath(path_bar, path_bar))
+ self.path.relpath("")
+ self.assertEqual("path!to!foo", self.path.relpath(path_foo))
+ self.assertEqual("..!foo", self.path.relpath(path_foo, path_bar))
+ self.assertEqual(
+ "..!..!..%s" % path_other, self.path.relpath(path_other, path_bar)
+ )
+ self.assertEqual(".", self.path.relpath(path_bar, path_bar))
def test_realpath_vs_abspath(self):
self.filesystem.is_windows_fs = False
- self.filesystem.create_file('!george!washington!bridge')
- self.filesystem.create_symlink('!first!president',
- '!george!washington')
- self.assertEqual('!first!president!bridge',
- self.os.path.abspath('!first!president!bridge'))
- self.assertEqual('!george!washington!bridge',
- self.os.path.realpath('!first!president!bridge'))
- self.os.chdir('!first!president')
- self.assertEqual('!george!washington!bridge',
- self.os.path.realpath('bridge'))
+ self.filesystem.create_file("!george!washington!bridge")
+ self.filesystem.create_symlink("!first!president", "!george!washington")
+ self.assertEqual(
+ "!first!president!bridge",
+ self.os.path.abspath("!first!president!bridge"),
+ )
+ self.assertEqual(
+ "!george!washington!bridge",
+ self.os.path.realpath("!first!president!bridge"),
+ )
+ self.os.chdir("!first!president")
+ self.assertEqual("!george!washington!bridge", self.os.path.realpath("bridge"))
@unittest.skipIf(sys.version_info < (3, 10), "'strict' new in Python 3.10")
def test_realpath_strict(self):
- self.filesystem.create_file('!foo!bar')
- self.filesystem.cwd = '!foo'
- self.assertEqual('!foo!baz',
- self.os.path.realpath('baz', strict=False))
+ self.filesystem.create_file("!foo!bar")
+ root_dir = self.filesystem.root_dir_name
+ self.filesystem.cwd = f"{root_dir}foo"
+ self.assertEqual(
+ f"{root_dir}foo!baz", self.os.path.realpath("baz", strict=False)
+ )
with self.raises_os_error(errno.ENOENT):
- self.os.path.realpath('baz', strict=True)
- self.assertEqual('!foo!bar',
- self.os.path.realpath('bar', strict=True))
+ self.os.path.realpath("baz", strict=True)
+ self.assertEqual(
+ f"{root_dir}foo!bar", self.os.path.realpath("bar", strict=True)
+ )
def test_samefile(self):
- file_path1 = '!foo!bar!baz'
- file_path2 = '!foo!bar!boo'
+ file_path1 = "!foo!bar!baz"
+ file_path2 = "!foo!bar!boo"
self.filesystem.create_file(file_path1)
self.filesystem.create_file(file_path2)
self.assertTrue(self.path.samefile(file_path1, file_path1))
self.assertFalse(self.path.samefile(file_path1, file_path2))
- self.assertTrue(
- self.path.samefile(file_path1, '!foo!..!foo!bar!..!bar!baz'))
- self.assertTrue(
- self.path.samefile(file_path1, b'!foo!..!foo!bar!..!bar!baz'))
+ self.assertTrue(self.path.samefile(file_path1, "!foo!..!foo!bar!..!bar!baz"))
+ self.assertTrue(self.path.samefile(file_path1, b"!foo!..!foo!bar!..!bar!baz"))
def test_exists(self):
- file_path = 'foo!bar!baz'
- file_path_bytes = b'foo!bar!baz'
+ file_path = "foo!bar!baz"
+ file_path_bytes = b"foo!bar!baz"
self.filesystem.create_file(file_path)
self.assertTrue(self.path.exists(file_path))
self.assertTrue(self.path.exists(file_path_bytes))
- self.assertFalse(self.path.exists('!some!other!bogus!path'))
+ self.assertFalse(self.path.exists("!some!other!bogus!path"))
+
+ def test_exists_with_drive(self):
+ self.filesystem.os = OSType.WINDOWS
+ self.filesystem.add_mount_point("F:")
+ self.assertTrue(self.path.exists("C:"))
+ self.assertTrue(self.path.exists("c:\\"))
+ self.assertTrue(self.path.exists("f:"))
+ self.assertTrue(self.path.exists("F:\\"))
+ self.assertFalse(self.path.exists("Z:"))
+ self.assertFalse(self.path.exists("z:\\"))
def test_lexists(self):
- file_path = 'foo!bar!baz'
- file_path_bytes = b'foo!bar!baz'
- self.filesystem.create_dir('foo!bar')
- self.filesystem.create_symlink(file_path, 'bogus')
+ file_path = "foo!bar!baz"
+ file_path_bytes = b"foo!bar!baz"
+ self.filesystem.create_dir("foo!bar")
+ self.filesystem.create_symlink(file_path, "bogus")
self.assertTrue(self.path.lexists(file_path))
self.assertTrue(self.path.lexists(file_path_bytes))
self.assertFalse(self.path.exists(file_path))
self.assertFalse(self.path.exists(file_path_bytes))
- self.filesystem.create_file('foo!bar!bogus')
+ self.filesystem.create_file("foo!bar!bogus")
self.assertTrue(self.path.exists(file_path))
def test_dirname_with_drive(self):
self.filesystem.is_windows_fs = True
- self.assertEqual('c:!foo',
- self.path.dirname('c:!foo!bar'))
- self.assertEqual(b'c:!',
- self.path.dirname(b'c:!foo'))
- self.assertEqual('!foo',
- self.path.dirname('!foo!bar'))
- self.assertEqual(b'!',
- self.path.dirname(b'!foo'))
- self.assertEqual('c:foo',
- self.path.dirname('c:foo!bar'))
- self.assertEqual(b'c:',
- self.path.dirname(b'c:foo'))
- self.assertEqual('foo',
- self.path.dirname('foo!bar'))
+ self.assertEqual("c:!foo", self.path.dirname("c:!foo!bar"))
+ self.assertEqual(b"c:!", self.path.dirname(b"c:!foo"))
+ self.assertEqual("!foo", self.path.dirname("!foo!bar"))
+ self.assertEqual(b"!", self.path.dirname(b"!foo"))
+ self.assertEqual("c:foo", self.path.dirname("c:foo!bar"))
+ self.assertEqual(b"c:", self.path.dirname(b"c:foo"))
+ self.assertEqual("foo", self.path.dirname("foo!bar"))
def test_dirname(self):
- dirname = 'foo!bar'
- self.assertEqual(dirname, self.path.dirname('%s!baz' % dirname))
+ dirname = "foo!bar"
+ self.assertEqual(dirname, self.path.dirname("%s!baz" % dirname))
def test_join_strings(self):
- components = ['foo', 'bar', 'baz']
- self.assertEqual('foo!bar!baz', self.path.join(*components))
+ components = ["foo", "bar", "baz"]
+ self.assertEqual("foo!bar!baz", self.path.join(*components))
def test_join_bytes(self):
- components = [b'foo', b'bar', b'baz']
- self.assertEqual(b'foo!bar!baz', self.path.join(*components))
+ components = [b"foo", b"bar", b"baz"]
+ self.assertEqual(b"foo!bar!baz", self.path.join(*components))
- def test_expand_user(self):
- if self.is_windows:
- self.assertEqual(self.path.expanduser('~'),
- self.os.environ['USERPROFILE'].replace('\\', '!'))
- else:
- self.assertEqual(self.path.expanduser('~'),
- self.os.environ['HOME'].replace('/', '!'))
+ @unittest.skipIf(sys.platform != "win32", "Windows specific test")
+ @patch.dict(os.environ, {"USERPROFILE": r"C:\Users\John"})
+ def test_expand_user_windows(self):
+ self.assertEqual(self.path.expanduser("~"), "C:!Users!John")
- @unittest.skipIf(TestCase.is_windows or TestCase.is_cygwin,
- 'only tested on unix systems')
+ @unittest.skipIf(sys.platform == "win32", "Posix specific test")
+ @patch.dict(os.environ, {"HOME": "/home/john"})
+ def test_expand_user(self):
+ self.assertEqual(self.path.expanduser("~"), "!home!john")
+
+ @patch.dict(os.environ, {}, clear=True)
+ def test_expand_user_no_home_environment(self):
+ """Make sure this also works without HOME / USERPROFILE set"""
+ # we just check that it does not crash and has some result,
+ # as the result is system-dependent
+ self.assertTrue(self.path.expanduser("~"))
+
+ @unittest.skipIf(
+ TestCase.is_windows or TestCase.is_cygwin,
+ "only tested on unix systems",
+ )
def test_expand_root(self):
- if sys.platform == 'darwin':
- roothome = '!var!root'
+ if sys.platform == "darwin":
+ roothome = "!var!root"
else:
- roothome = '!root'
- self.assertEqual(self.path.expanduser('~root'), roothome)
+ roothome = "!root"
+ self.assertEqual(self.path.expanduser("~root"), roothome)
def test_getsize_path_nonexistent(self):
- file_path = 'foo!bar!baz'
+ file_path = "foo!bar!baz"
with self.assertRaises(os.error):
self.path.getsize(file_path)
def test_getsize_file_empty(self):
- file_path = 'foo!bar!baz'
+ file_path = "foo!bar!baz"
self.filesystem.create_file(file_path)
self.assertEqual(0, self.path.getsize(file_path))
def test_getsize_file_non_zero_size(self):
- file_path = 'foo!bar!baz'
- file_path_bytes = b'foo!bar!baz'
- self.filesystem.create_file(file_path, contents='1234567')
+ file_path = "foo!bar!baz"
+ file_path_bytes = b"foo!bar!baz"
+ self.filesystem.create_file(file_path, contents="1234567")
self.assertEqual(7, self.path.getsize(file_path))
self.assertEqual(7, self.path.getsize(file_path_bytes))
def test_getsize_dir_empty(self):
# For directories, only require that the size is non-negative.
- dir_path = 'foo!bar'
+ dir_path = "foo!bar"
self.filesystem.create_dir(dir_path)
size = self.path.getsize(dir_path)
- self.assertFalse(int(size) < 0,
- 'expected non-negative size; actual: %s' % size)
+ self.assertFalse(int(size) < 0, "expected non-negative size; actual: %s" % size)
def test_getsize_dir_non_zero_size(self):
# For directories, only require that the size is non-negative.
- dir_path = 'foo!bar'
- self.filesystem.create_file(self.filesystem.joinpaths(dir_path, 'baz'))
+ dir_path = "foo!bar"
+ self.filesystem.create_file(self.filesystem.joinpaths(dir_path, "baz"))
size = self.path.getsize(dir_path)
- self.assertFalse(int(size) < 0,
- 'expected non-negative size; actual: %s' % size)
+ self.assertFalse(int(size) < 0, "expected non-negative size; actual: %s" % size)
def test_isdir(self):
- self.filesystem.create_file('foo!bar')
- self.assertTrue(self.path.isdir('foo'))
- self.assertTrue(self.path.isdir(b'foo'))
- self.assertFalse(self.path.isdir('foo!bar'))
- self.assertFalse(self.path.isdir('it_dont_exist'))
+ self.filesystem.create_file("foo!bar")
+ self.assertTrue(self.path.isdir("foo"))
+ self.assertTrue(self.path.isdir(b"foo"))
+ self.assertFalse(self.path.isdir("foo!bar"))
+ self.assertFalse(self.path.isdir("it_dont_exist"))
def test_isdir_with_cwd_change(self):
- self.filesystem.create_file('!foo!bar!baz')
- self.assertTrue(self.path.isdir('!foo'))
- self.assertTrue(self.path.isdir('!foo!bar'))
- self.assertTrue(self.path.isdir('foo'))
- self.assertTrue(self.path.isdir('foo!bar'))
- self.filesystem.cwd = '!foo'
- self.assertTrue(self.path.isdir('!foo'))
- self.assertTrue(self.path.isdir('!foo!bar'))
- self.assertTrue(self.path.isdir('bar'))
+ self.filesystem.create_file("!foo!bar!baz")
+ self.assertTrue(self.path.isdir("!foo"))
+ self.assertTrue(self.path.isdir("!foo!bar"))
+ self.assertTrue(self.path.isdir("foo"))
+ self.assertTrue(self.path.isdir("foo!bar"))
+ self.filesystem.cwd = f"{self.filesystem.root_dir_name}foo"
+ self.assertTrue(self.path.isdir("!foo"))
+ self.assertTrue(self.path.isdir("!foo!bar"))
+ self.assertTrue(self.path.isdir("bar"))
def test_isfile(self):
- self.filesystem.create_file('foo!bar')
- self.assertFalse(self.path.isfile('foo'))
- self.assertTrue(self.path.isfile('foo!bar'))
- self.assertTrue(self.path.isfile(b'foo!bar'))
- self.assertFalse(self.path.isfile('it_dont_exist'))
+ self.filesystem.create_file("foo!bar")
+ self.assertFalse(self.path.isfile("foo"))
+ self.assertTrue(self.path.isfile("foo!bar"))
+ self.assertTrue(self.path.isfile(b"foo!bar"))
+ self.assertFalse(self.path.isfile("it_dont_exist"))
def test_get_mtime(self):
- test_file = self.filesystem.create_file('foo!bar1.txt')
- self.assertNotEqual(24, self.path.getmtime('foo!bar1.txt'))
+ test_file = self.filesystem.create_file("foo!bar1.txt")
+ self.assertNotEqual(24, self.path.getmtime("foo!bar1.txt"))
test_file.st_mtime = 24
- self.assertEqual(24, self.path.getmtime('foo!bar1.txt'))
- self.assertEqual(24, self.path.getmtime(b'foo!bar1.txt'))
+ self.assertEqual(24, self.path.getmtime("foo!bar1.txt"))
+ self.assertEqual(24, self.path.getmtime(b"foo!bar1.txt"))
def test_get_mtime_raises_os_error(self):
- self.assertFalse(self.path.exists('does_not_exist'))
+ self.assertFalse(self.path.exists("does_not_exist"))
with self.raises_os_error(errno.ENOENT):
- self.path.getmtime('does_not_exist')
+ self.path.getmtime("does_not_exist")
def test_islink(self):
- self.filesystem.create_dir('foo')
- self.filesystem.create_file('foo!regular_file')
- self.filesystem.create_symlink('foo!link_to_file', 'regular_file')
- self.assertFalse(self.path.islink('foo'))
+ self.filesystem.create_dir("foo")
+ self.filesystem.create_file("foo!regular_file")
+ self.filesystem.create_symlink("foo!link_to_file", "regular_file")
+ self.assertFalse(self.path.islink("foo"))
# An object can be both a link and a file or file, according to the
# comments in Python/Lib/posixpath.py.
- self.assertTrue(self.path.islink('foo!link_to_file'))
- self.assertTrue(self.path.isfile('foo!link_to_file'))
- self.assertTrue(self.path.islink(b'foo!link_to_file'))
- self.assertTrue(self.path.isfile(b'foo!link_to_file'))
+ self.assertTrue(self.path.islink("foo!link_to_file"))
+ self.assertTrue(self.path.isfile("foo!link_to_file"))
+ self.assertTrue(self.path.islink(b"foo!link_to_file"))
+ self.assertTrue(self.path.isfile(b"foo!link_to_file"))
- self.assertTrue(self.path.isfile('foo!regular_file'))
- self.assertFalse(self.path.islink('foo!regular_file'))
+ self.assertTrue(self.path.isfile("foo!regular_file"))
+ self.assertFalse(self.path.islink("foo!regular_file"))
- self.assertFalse(self.path.islink('it_dont_exist'))
+ self.assertFalse(self.path.islink("it_dont_exist"))
def test_is_link_case_sensitive(self):
# Regression test for #306
self.filesystem.is_case_sensitive = False
- self.filesystem.create_dir('foo')
- self.filesystem.create_symlink('foo!bar', 'foo')
- self.assertTrue(self.path.islink('foo!Bar'))
+ self.filesystem.create_dir("foo")
+ self.filesystem.create_symlink("foo!bar", "foo")
+ self.assertTrue(self.path.islink("foo!Bar"))
def test_ismount(self):
- self.assertFalse(self.path.ismount(''))
- self.assertTrue(self.path.ismount('!'))
- self.assertTrue(self.path.ismount(b'!'))
- self.assertFalse(self.path.ismount('!mount!'))
- self.filesystem.add_mount_point('!mount')
- self.assertTrue(self.path.ismount('!mount'))
- self.assertTrue(self.path.ismount(b'!mount'))
- self.assertTrue(self.path.ismount('!mount!'))
+ self.assertFalse(self.path.ismount(""))
+ self.assertTrue(self.path.ismount("!"))
+ self.assertTrue(self.path.ismount(b"!"))
+ self.assertFalse(self.path.ismount("!mount!"))
+ self.filesystem.add_mount_point("!mount")
+ self.assertTrue(self.path.ismount("!mount"))
+ self.assertTrue(self.path.ismount(b"!mount"))
+ self.assertTrue(self.path.ismount("!mount!"))
def test_ismount_with_drive_letters(self):
self.filesystem.is_windows_fs = True
- self.assertTrue(self.path.ismount('!'))
- self.assertTrue(self.path.ismount('c:!'))
- self.assertFalse(self.path.ismount('c:'))
- self.assertTrue(self.path.ismount('z:!'))
- self.filesystem.add_mount_point('!mount')
- self.assertTrue(self.path.ismount('!mount'))
- self.assertTrue(self.path.ismount('!mount!'))
+ self.assertTrue(self.path.ismount("!"))
+ self.assertTrue(self.path.ismount("c:!"))
+ self.assertFalse(self.path.ismount("c:"))
+ self.assertTrue(self.path.ismount("z:!"))
+ self.filesystem.add_mount_point("!mount")
+ self.assertTrue(self.path.ismount("!mount"))
+ self.assertTrue(self.path.ismount("!mount!"))
def test_ismount_with_unc_paths(self):
self.filesystem.is_windows_fs = True
- self.assertTrue(self.path.ismount('!!a!'))
- self.assertTrue(self.path.ismount('!!a!b'))
- self.assertTrue(self.path.ismount('!!a!b!'))
- self.assertFalse(self.path.ismount('!a!b!'))
- self.assertFalse(self.path.ismount('!!a!b!c'))
+ self.assertTrue(self.path.ismount("!!a!"))
+ self.assertTrue(self.path.ismount("!!a!b"))
+ self.assertTrue(self.path.ismount("!!a!b!"))
+ self.assertFalse(self.path.ismount("!a!b!"))
+ self.assertFalse(self.path.ismount("!!a!b!c"))
def test_ismount_with_alternate_path_separator(self):
- self.filesystem.alternative_path_separator = '!'
- self.filesystem.add_mount_point('!mount')
- self.assertTrue(self.path.ismount('!mount'))
- self.assertTrue(self.path.ismount('!mount!'))
- self.assertTrue(self.path.ismount('!mount!!'))
+ self.filesystem.alternative_path_separator = "!"
+ self.filesystem.add_mount_point("!mount")
+ self.assertTrue(self.path.ismount("!mount"))
+ self.assertTrue(self.path.ismount("!mount!"))
+ self.assertTrue(self.path.ismount("!mount!!"))
self.filesystem.is_windows_fs = True
- self.assertTrue(self.path.ismount('Z:!'))
+ self.assertTrue(self.path.ismount("Z:!"))
def test_getattr_forward_to_real_os_path(self):
"""Forwards any non-faked calls to os.path."""
- self.assertTrue(hasattr(self.path, 'sep'),
- 'Get a faked os.path function')
+ self.assertTrue(hasattr(self.path, "sep"), "Get a faked os.path function")
private_path_function = None
if sys.version_info < (3, 6):
if self.is_windows:
- private_path_function = '_get_bothseps'
+ private_path_function = "_get_bothseps"
else:
- private_path_function = '_join_real_path'
+ private_path_function = "_join_real_path"
if private_path_function:
- self.assertTrue(hasattr(self.path, private_path_function),
- 'Get a real os.path function '
- 'not implemented in fake os.path')
- self.assertFalse(hasattr(self.path, 'nonexistent'))
+ self.assertTrue(
+ hasattr(self.path, private_path_function),
+ "Get a real os.path function " "not implemented in fake os.path",
+ )
+ self.assertFalse(hasattr(self.path, "nonexistent"))
+
+ def test_splitroot_posix(self):
+ self.filesystem.is_windows_fs = False
+ self.assertEqual(("", "", "foo!bar"), self.filesystem.splitroot("foo!bar"))
+ self.assertEqual(("", "!", "foo!bar"), self.filesystem.splitroot("!foo!bar"))
+ self.assertEqual(
+ ("", "!!", "foo!!bar"), self.filesystem.splitroot("!!foo!!bar")
+ )
class PathManipulationTestBase(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='|')
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="|")
class CollapsePathPipeSeparatorTest(PathManipulationTestBase):
@@ -1187,53 +1255,48 @@ class CollapsePathPipeSeparatorTest(PathManipulationTestBase):
as path separator."""
def test_empty_path_becomes_dot_path(self):
- self.assertEqual('.', self.filesystem.normpath(''))
+ self.assertEqual(".", self.filesystem.normpath(""))
def test_dot_path_unchanged(self):
- self.assertEqual('.', self.filesystem.normpath('.'))
+ self.assertEqual(".", self.filesystem.normpath("."))
def test_slashes_are_not_collapsed(self):
"""Tests that '/' is not treated specially if the
- path separator is '|'.
+ path separator is '|'.
- In particular, multiple slashes should not be collapsed.
- """
- self.assertEqual('/', self.filesystem.normpath('/'))
- self.assertEqual('/////', self.filesystem.normpath('/////'))
+ In particular, multiple slashes should not be collapsed.
+ """
+ self.assertEqual("/", self.filesystem.normpath("/"))
+ self.assertEqual("/////", self.filesystem.normpath("/////"))
def test_root_path(self):
- self.assertEqual('|', self.filesystem.normpath('|'))
+ self.assertEqual("|", self.filesystem.normpath("|"))
def test_multiple_separators_collapsed_into_root_path(self):
- self.assertEqual('|', self.filesystem.normpath('|||||'))
+ self.assertEqual("|", self.filesystem.normpath("|||||"))
def test_all_dot_paths_removed_but_one(self):
- self.assertEqual('.', self.filesystem.normpath('.|.|.|.'))
+ self.assertEqual(".", self.filesystem.normpath(".|.|.|."))
def test_all_dot_paths_removed_if_another_path_component_exists(self):
- self.assertEqual('|', self.filesystem.normpath('|.|.|.|'))
- self.assertEqual('foo|bar', self.filesystem.normpath('foo|.|.|.|bar'))
+ self.assertEqual("|", self.filesystem.normpath("|.|.|.|"))
+ self.assertEqual("foo|bar", self.filesystem.normpath("foo|.|.|.|bar"))
def test_ignores_up_level_references_starting_from_root(self):
- self.assertEqual('|', self.filesystem.normpath('|..|..|..|'))
- self.assertEqual(
- '|', self.filesystem.normpath('|..|..|foo|bar|..|..|'))
+ self.assertEqual("|", self.filesystem.normpath("|..|..|..|"))
+ self.assertEqual("|", self.filesystem.normpath("|..|..|foo|bar|..|..|"))
self.filesystem.is_windows_fs = False # not an UNC path
- self.assertEqual('|', self.filesystem.normpath('||..|.|..||'))
+ self.assertEqual("|", self.filesystem.normpath("||..|.|..||"))
def test_conserves_up_level_references_starting_from_current_dir(self):
- self.assertEqual(
- '..|..', self.filesystem.normpath('..|foo|bar|..|..|..'))
+ self.assertEqual("..|..", self.filesystem.normpath("..|foo|bar|..|..|.."))
def test_combine_dot_and_up_level_references_in_absolute_path(self):
- self.assertEqual(
- '|yes', self.filesystem.normpath('|||||.|..|||yes|no|..|.|||'))
+ self.assertEqual("|yes", self.filesystem.normpath("|||||.|..|||yes|no|..|.|||"))
def test_dots_in_path_collapses_to_last_path(self):
- self.assertEqual(
- 'bar', self.filesystem.normpath('foo|..|bar'))
- self.assertEqual(
- 'bar', self.filesystem.normpath('foo|..|yes|..|no|..|bar'))
+ self.assertEqual("bar", self.filesystem.normpath("foo|..|bar"))
+ self.assertEqual("bar", self.filesystem.normpath("foo|..|yes|..|no|..|bar"))
class SplitPathTest(PathManipulationTestBase):
@@ -1241,158 +1304,163 @@ class SplitPathTest(PathManipulationTestBase):
using | as path separator."""
def test_empty_path(self):
- self.assertEqual(('', ''), self.filesystem.splitpath(''))
+ self.assertEqual(("", ""), self.filesystem.splitpath(""))
def test_no_separators(self):
- self.assertEqual(('', 'ab'), self.filesystem.splitpath('ab'))
+ self.assertEqual(("", "ab"), self.filesystem.splitpath("ab"))
def test_slashes_do_not_split(self):
"""Tests that '/' is not treated specially if the
path separator is '|'."""
- self.assertEqual(('', 'a/b'), self.filesystem.splitpath('a/b'))
+ self.assertEqual(("", "a/b"), self.filesystem.splitpath("a/b"))
def test_eliminate_trailing_separators_from_head(self):
- self.assertEqual(('a', 'b'), self.filesystem.splitpath('a|b'))
- self.assertEqual(('a', 'b'), self.filesystem.splitpath('a|||b'))
- self.assertEqual(('|a', 'b'), self.filesystem.splitpath('|a||b'))
- self.assertEqual(('a|b', 'c'), self.filesystem.splitpath('a|b|c'))
- self.assertEqual(('|a|b', 'c'), self.filesystem.splitpath('|a|b|c'))
+ self.assertEqual(("a", "b"), self.filesystem.splitpath("a|b"))
+ self.assertEqual(("a", "b"), self.filesystem.splitpath("a|||b"))
+ self.assertEqual(("|a", "b"), self.filesystem.splitpath("|a||b"))
+ self.assertEqual(("a|b", "c"), self.filesystem.splitpath("a|b|c"))
+ self.assertEqual(("|a|b", "c"), self.filesystem.splitpath("|a|b|c"))
def test_root_separator_is_not_stripped(self):
- self.assertEqual(('|||', ''), self.filesystem.splitpath('|||'))
- self.assertEqual(('|', 'a'), self.filesystem.splitpath('|a'))
- self.assertEqual(('|||', 'a'), self.filesystem.splitpath('|||a'))
+ self.assertEqual(("|||", ""), self.filesystem.splitpath("|||"))
+ self.assertEqual(("|", "a"), self.filesystem.splitpath("|a"))
+ self.assertEqual(("|||", "a"), self.filesystem.splitpath("|||a"))
def test_empty_tail_if_path_ends_in_separator(self):
- self.assertEqual(('a|b', ''), self.filesystem.splitpath('a|b|'))
+ self.assertEqual(("a|b", ""), self.filesystem.splitpath("a|b|"))
def test_empty_path_components_are_preserved_in_head(self):
- self.assertEqual(('|a||b', 'c'), self.filesystem.splitpath('|a||b||c'))
+ self.assertEqual(("|a||b", "c"), self.filesystem.splitpath("|a||b||c"))
class JoinPathTest(PathManipulationTestBase):
"""Tests JoinPath (which mimics os.path.join) using | as path separator."""
def test_one_empty_component(self):
- self.assertEqual('', self.filesystem.joinpaths(''))
+ self.assertEqual("", self.filesystem.joinpaths(""))
def test_multiple_empty_components(self):
- self.assertEqual('', self.filesystem.joinpaths('', '', ''))
+ self.assertEqual("", self.filesystem.joinpaths("", "", ""))
def test_separators_not_stripped_from_single_component(self):
- self.assertEqual('||a||', self.filesystem.joinpaths('||a||'))
+ self.assertEqual("||a||", self.filesystem.joinpaths("||a||"))
def test_one_separator_added_between_components(self):
- self.assertEqual('a|b|c|d',
- self.filesystem.joinpaths('a', 'b', 'c', 'd'))
+ self.assertEqual("a|b|c|d", self.filesystem.joinpaths("a", "b", "c", "d"))
def test_no_separator_added_for_components_ending_in_separator(self):
- self.assertEqual('a|b|c', self.filesystem.joinpaths('a|', 'b|', 'c'))
- self.assertEqual('a|||b|||c',
- self.filesystem.joinpaths('a|||', 'b|||', 'c'))
+ self.assertEqual("a|b|c", self.filesystem.joinpaths("a|", "b|", "c"))
+ self.assertEqual("a|||b|||c", self.filesystem.joinpaths("a|||", "b|||", "c"))
def test_components_preceding_absolute_component_are_ignored(self):
- self.assertEqual('|c|d',
- self.filesystem.joinpaths('a', '|b', '|c', 'd'))
+ self.assertEqual("|c|d", self.filesystem.joinpaths("a", "|b", "|c", "d"))
def test_one_separator_added_for_trailing_empty_components(self):
- self.assertEqual('a|', self.filesystem.joinpaths('a', ''))
- self.assertEqual('a|', self.filesystem.joinpaths('a', '', ''))
+ self.assertEqual("a|", self.filesystem.joinpaths("a", ""))
+ self.assertEqual("a|", self.filesystem.joinpaths("a", "", ""))
def test_no_separator_added_for_leading_empty_components(self):
- self.assertEqual('a', self.filesystem.joinpaths('', 'a'))
+ self.assertEqual("a", self.filesystem.joinpaths("", "a"))
def test_internal_empty_components_ignored(self):
- self.assertEqual('a|b', self.filesystem.joinpaths('a', '', 'b'))
- self.assertEqual('a|b|', self.filesystem.joinpaths('a|', '', 'b|'))
+ self.assertEqual("a|b", self.filesystem.joinpaths("a", "", "b"))
+ self.assertEqual("a|b|", self.filesystem.joinpaths("a|", "", "b|"))
class PathSeparatorTest(TestCase):
def test_os_path_sep_matches_fake_filesystem_separator(self):
- filesystem = fake_filesystem.FakeFilesystem(path_separator='!')
- fake_os = fake_filesystem.FakeOsModule(filesystem)
- self.assertEqual('!', fake_os.sep)
- self.assertEqual('!', fake_os.path.sep)
+ filesystem = fake_filesystem.FakeFilesystem(path_separator="!")
+ fake_os_module = fake_os.FakeOsModule(filesystem)
+ self.assertEqual("!", fake_os_module.sep)
+ self.assertEqual("!", fake_os_module.path.sep)
class NormalizeCaseTest(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
self.filesystem.is_case_sensitive = False
def test_normalize_case(self):
- self.filesystem.create_file('/Foo/Bar')
- self.assertEqual('/Foo/Bar',
- self.filesystem._original_path('/foo/bar'))
- self.assertEqual('/Foo/Bar',
- self.filesystem._original_path('/FOO/BAR'))
+ self.filesystem.create_file("/Foo/Bar")
+ self.assertEqual(
+ f"{self.filesystem.root_dir_name}Foo/Bar",
+ self.filesystem._original_path("/foo/bar"),
+ )
+ self.assertEqual(
+ f"{self.filesystem.root_dir_name}Foo/Bar",
+ self.filesystem._original_path("/FOO/BAR"),
+ )
def test_normalize_case_for_drive(self):
self.filesystem.is_windows_fs = True
- self.filesystem.create_file('C:/Foo/Bar')
- self.assertEqual('C:/Foo/Bar',
- self.filesystem._original_path('c:/foo/bar'))
- self.assertEqual('C:/Foo/Bar',
- self.filesystem._original_path('C:/FOO/BAR'))
+ self.filesystem.create_file("C:/Foo/Bar")
+ self.assertEqual("C:/Foo/Bar", self.filesystem._original_path("c:/foo/bar"))
+ self.assertEqual("C:/Foo/Bar", self.filesystem._original_path("C:/FOO/BAR"))
def test_normalize_case_for_non_existing_file(self):
- self.filesystem.create_dir('/Foo/Bar')
- self.assertEqual('/Foo/Bar/baz',
- self.filesystem._original_path('/foo/bar/baz'))
- self.assertEqual('/Foo/Bar/BAZ',
- self.filesystem._original_path('/FOO/BAR/BAZ'))
-
- @unittest.skipIf(not TestCase.is_windows,
- 'Regression test for Windows problem only')
+ self.filesystem.create_dir("/Foo/Bar")
+ self.assertEqual(
+ f"{self.filesystem.root_dir_name}Foo/Bar/baz",
+ self.filesystem._original_path("/foo/bar/baz"),
+ )
+ self.assertEqual(
+ f"{self.filesystem.root_dir_name}Foo/Bar/BAZ",
+ self.filesystem._original_path("/FOO/BAR/BAZ"),
+ )
+
+ @unittest.skipIf(
+ not TestCase.is_windows, "Regression test for Windows problem only"
+ )
def test_normalize_case_for_lazily_added_empty_file(self):
# regression test for specific issue with added empty real files
filesystem = fake_filesystem.FakeFilesystem()
- real_dir_path = os.path.split(
- os.path.dirname(os.path.abspath(__file__)))[0]
+ real_dir_path = os.path.split(os.path.dirname(os.path.abspath(__file__)))[0]
filesystem.add_real_directory(real_dir_path)
- initPyPath = os.path.join(real_dir_path, '__init__.py')
- self.assertEqual(initPyPath,
- filesystem._original_path(initPyPath.upper()))
+ initPyPath = os.path.join(real_dir_path, "__init__.py")
+ self.assertEqual(initPyPath, filesystem._original_path(initPyPath.upper()))
class AlternativePathSeparatorTest(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='!')
- self.filesystem.alternative_path_separator = '?'
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="!")
+ self.filesystem.alternative_path_separator = "?"
def test_initial_value(self):
filesystem = fake_filesystem.FakeFilesystem()
if self.is_windows:
- self.assertEqual('/', filesystem.alternative_path_separator)
+ self.assertEqual("/", filesystem.alternative_path_separator)
else:
self.assertIsNone(filesystem.alternative_path_separator)
- filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
+ filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
self.assertIsNone(filesystem.alternative_path_separator)
def test_alt_sep(self):
- fake_os = fake_filesystem.FakeOsModule(self.filesystem)
- self.assertEqual('?', fake_os.altsep)
- self.assertEqual('?', fake_os.path.altsep)
+ fake_os_module = fake_os.FakeOsModule(self.filesystem)
+ self.assertEqual("?", fake_os_module.altsep)
+ self.assertEqual("?", fake_os_module.path.altsep)
def test_collapse_path_with_mixed_separators(self):
- self.assertEqual('!foo!bar', self.filesystem.normpath('!foo??bar'))
+ self.assertEqual("!foo!bar", self.filesystem.normpath("!foo??bar"))
def test_normalize_path_with_mixed_separators(self):
- path = 'foo?..?bar'
- self.assertEqual('!bar', self.filesystem.absnormpath(path))
+ path = "foo?..?bar"
+ self.assertEqual(
+ f"{self.filesystem.root_dir_name}bar",
+ self.filesystem.absnormpath(path),
+ )
def test_exists_with_mixed_separators(self):
- self.filesystem.create_file('?foo?bar?baz')
- self.filesystem.create_file('!foo!bar!xyzzy!plugh')
- self.assertTrue(self.filesystem.exists('!foo!bar!baz'))
- self.assertTrue(self.filesystem.exists('?foo?bar?xyzzy?plugh'))
+ self.filesystem.create_file("?foo?bar?baz")
+ self.filesystem.create_file("!foo!bar!xyzzy!plugh")
+ self.assertTrue(self.filesystem.exists("!foo!bar!baz"))
+ self.assertTrue(self.filesystem.exists("?foo?bar?xyzzy?plugh"))
class DriveLetterSupportTest(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='!')
- self.filesystem.alternative_path_separator = '^'
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="!")
+ self.filesystem.alternative_path_separator = "^"
self.filesystem.is_windows_fs = True
def test_initial_value(self):
@@ -1403,518 +1471,535 @@ class DriveLetterSupportTest(TestCase):
self.assertFalse(filesystem.is_windows_fs)
def test_collapse_path(self):
- self.assertEqual('c:!foo!bar',
- self.filesystem.normpath('c:!!foo!!bar'))
+ self.assertEqual("c:!foo!bar", self.filesystem.normpath("c:!!foo!!bar"))
def test_collapse_unc_path(self):
- self.assertEqual('!!foo!bar!baz',
- self.filesystem.normpath('!!foo!bar!!baz!!'))
+ self.assertEqual("!!foo!bar!baz", self.filesystem.normpath("!!foo!bar!!baz!!"))
def test_normalize_path_str(self):
- self.filesystem.cwd = ''
- self.assertEqual('c:!foo!bar',
- self.filesystem.absnormpath('c:!foo!!bar'))
- self.filesystem.cwd = 'c:!foo'
- self.assertEqual('c:!foo!bar', self.filesystem.absnormpath('bar'))
+ self.filesystem.cwd = ""
+ self.assertEqual("c:!foo!bar", self.filesystem.absnormpath("c:!foo!!bar"))
+ self.filesystem.cwd = "c:!foo"
+ self.assertEqual("c:!foo!bar", self.filesystem.absnormpath("bar"))
def test_normalize_path_bytes(self):
- self.filesystem.cwd = b''
- self.assertEqual(b'c:!foo!bar',
- self.filesystem.absnormpath(b'c:!foo!!bar'))
- self.filesystem.cwd = b'c:!foo'
- self.assertEqual(b'c:!foo!bar', self.filesystem.absnormpath(b'bar'))
+ self.filesystem.cwd = b""
+ self.assertEqual(b"c:!foo!bar", self.filesystem.absnormpath(b"c:!foo!!bar"))
+ self.filesystem.cwd = b"c:!foo"
+ self.assertEqual(b"c:!foo!bar", self.filesystem.absnormpath(b"bar"))
def test_split_path_str(self):
- self.assertEqual(('c:!foo', 'bar'),
- self.filesystem.splitpath('c:!foo!bar'))
- self.assertEqual(('c:!', 'foo'),
- self.filesystem.splitpath('c:!foo'))
- self.assertEqual(('!foo', 'bar'),
- self.filesystem.splitpath('!foo!bar'))
- self.assertEqual(('!', 'foo'),
- self.filesystem.splitpath('!foo'))
- self.assertEqual(('c:foo', 'bar'),
- self.filesystem.splitpath('c:foo!bar'))
- self.assertEqual(('c:', 'foo'),
- self.filesystem.splitpath('c:foo'))
- self.assertEqual(('foo', 'bar'),
- self.filesystem.splitpath('foo!bar'))
+ self.assertEqual(("c:!foo", "bar"), self.filesystem.splitpath("c:!foo!bar"))
+ self.assertEqual(("c:!", "foo"), self.filesystem.splitpath("c:!foo"))
+ self.assertEqual(("!foo", "bar"), self.filesystem.splitpath("!foo!bar"))
+ self.assertEqual(("!", "foo"), self.filesystem.splitpath("!foo"))
+ self.assertEqual(("c:foo", "bar"), self.filesystem.splitpath("c:foo!bar"))
+ self.assertEqual(("c:", "foo"), self.filesystem.splitpath("c:foo"))
+ self.assertEqual(("foo", "bar"), self.filesystem.splitpath("foo!bar"))
def test_split_with_alt_separator(self):
- self.assertEqual(('a^b', 'c'), self.filesystem.splitpath('a^b^c'))
- self.assertEqual(('a^b!c', 'd'), self.filesystem.splitpath('a^b!c^d'))
- self.assertEqual(('a^b!c', 'd'), self.filesystem.splitpath('a^b!c!d'))
- self.assertEqual((b'a^b', b'c'), self.filesystem.splitpath(b'a^b^c'))
- self.assertEqual((b'a^b!c', b'd'),
- self.filesystem.splitpath(b'a^b!c^d'))
- self.assertEqual((b'a^b!c', b'd'),
- self.filesystem.splitpath(b'a^b!c!d'))
+ self.assertEqual(("a^b", "c"), self.filesystem.splitpath("a^b^c"))
+ self.assertEqual(("a^b!c", "d"), self.filesystem.splitpath("a^b!c^d"))
+ self.assertEqual(("a^b!c", "d"), self.filesystem.splitpath("a^b!c!d"))
+ self.assertEqual((b"a^b", b"c"), self.filesystem.splitpath(b"a^b^c"))
+ self.assertEqual((b"a^b!c", b"d"), self.filesystem.splitpath(b"a^b!c^d"))
+ self.assertEqual((b"a^b!c", b"d"), self.filesystem.splitpath(b"a^b!c!d"))
def test_split_path_bytes(self):
- self.assertEqual((b'c:!foo', b'bar'),
- self.filesystem.splitpath(b'c:!foo!bar'))
- self.assertEqual((b'c:!', b'foo'),
- self.filesystem.splitpath(b'c:!foo'))
- self.assertEqual((b'!foo', b'bar'),
- self.filesystem.splitpath(b'!foo!bar'))
- self.assertEqual((b'!', b'foo'),
- self.filesystem.splitpath(b'!foo'))
- self.assertEqual((b'c:foo', b'bar'),
- self.filesystem.splitpath(b'c:foo!bar'))
- self.assertEqual((b'c:', b'foo'),
- self.filesystem.splitpath(b'c:foo'))
- self.assertEqual((b'foo', b'bar'),
- self.filesystem.splitpath(b'foo!bar'))
+ self.assertEqual((b"c:!foo", b"bar"), self.filesystem.splitpath(b"c:!foo!bar"))
+ self.assertEqual((b"c:!", b"foo"), self.filesystem.splitpath(b"c:!foo"))
+ self.assertEqual((b"!foo", b"bar"), self.filesystem.splitpath(b"!foo!bar"))
+ self.assertEqual((b"!", b"foo"), self.filesystem.splitpath(b"!foo"))
+ self.assertEqual((b"c:foo", b"bar"), self.filesystem.splitpath(b"c:foo!bar"))
+ self.assertEqual((b"c:", b"foo"), self.filesystem.splitpath(b"c:foo"))
+ self.assertEqual((b"foo", b"bar"), self.filesystem.splitpath(b"foo!bar"))
def test_characters_before_root_ignored_in_join_paths(self):
- self.assertEqual('c:d', self.filesystem.joinpaths('b', 'c:', 'd'))
+ self.assertEqual("c:d", self.filesystem.joinpaths("b", "c:", "d"))
def test_resolve_path(self):
- self.assertEqual('c:!foo!bar',
- self.filesystem.resolve_path('c:!foo!bar'))
+ self.assertEqual("C:!foo!bar", self.filesystem.resolve_path("C:!foo!bar"))
def test_get_path_components(self):
- self.assertEqual(['c:', 'foo', 'bar'],
- self.filesystem._path_components('c:!foo!bar'))
- self.assertEqual(['c:'], self.filesystem._path_components('c:'))
+ self.assertEqual(
+ ["c:", "foo", "bar"],
+ self.filesystem._path_components("c:!foo!bar"),
+ )
+ self.assertEqual(["c:"], self.filesystem._path_components("c:"))
def test_split_drive_str(self):
- self.assertEqual(('c:', '!foo!bar'),
- self.filesystem.splitdrive('c:!foo!bar'))
- self.assertEqual(('', '!foo!bar'),
- self.filesystem.splitdrive('!foo!bar'))
- self.assertEqual(('c:', 'foo!bar'),
- self.filesystem.splitdrive('c:foo!bar'))
- self.assertEqual(('', 'foo!bar'),
- self.filesystem.splitdrive('foo!bar'))
+ self.assertEqual(("c:", "!foo!bar"), self.filesystem.splitdrive("c:!foo!bar"))
+ self.assertEqual(("", "!foo!bar"), self.filesystem.splitdrive("!foo!bar"))
+ self.assertEqual(("c:", "foo!bar"), self.filesystem.splitdrive("c:foo!bar"))
+ self.assertEqual(("", "foo!bar"), self.filesystem.splitdrive("foo!bar"))
def test_split_drive_bytes(self):
- self.assertEqual((b'c:', b'!foo!bar'),
- self.filesystem.splitdrive(b'c:!foo!bar'))
- self.assertEqual((b'', b'!foo!bar'),
- self.filesystem.splitdrive(b'!foo!bar'))
+ self.assertEqual(
+ (b"c:", b"!foo!bar"), self.filesystem.splitdrive(b"c:!foo!bar")
+ )
+ self.assertEqual((b"", b"!foo!bar"), self.filesystem.splitdrive(b"!foo!bar"))
def test_split_drive_alt_sep(self):
- self.assertEqual(('c:', '^foo^bar'),
- self.filesystem.splitdrive('c:^foo^bar'))
- self.assertEqual(('', 'foo^bar'),
- self.filesystem.splitdrive('foo^bar'))
- self.assertEqual(('', 'foo^bar!baz'),
- self.filesystem.splitdrive('foo^bar!baz'))
- self.assertEqual((b'c:', b'^foo^bar'),
- self.filesystem.splitdrive(b'c:^foo^bar'))
- self.assertEqual((b'', b'^foo^bar'),
- self.filesystem.splitdrive(b'^foo^bar'))
- self.assertEqual((b'', b'^foo^bar!baz'),
- self.filesystem.splitdrive(b'^foo^bar!baz'))
+ self.assertEqual(("c:", "^foo^bar"), self.filesystem.splitdrive("c:^foo^bar"))
+ self.assertEqual(("", "foo^bar"), self.filesystem.splitdrive("foo^bar"))
+ self.assertEqual(("", "foo^bar!baz"), self.filesystem.splitdrive("foo^bar!baz"))
+ self.assertEqual(
+ (b"c:", b"^foo^bar"), self.filesystem.splitdrive(b"c:^foo^bar")
+ )
+ self.assertEqual((b"", b"^foo^bar"), self.filesystem.splitdrive(b"^foo^bar"))
+ self.assertEqual(
+ (b"", b"^foo^bar!baz"), self.filesystem.splitdrive(b"^foo^bar!baz")
+ )
def test_split_drive_with_unc_path(self):
- self.assertEqual(('!!foo!bar', '!baz'),
- self.filesystem.splitdrive('!!foo!bar!baz'))
- self.assertEqual(('', '!!foo'), self.filesystem.splitdrive('!!foo'))
- self.assertEqual(('', '!!foo!!bar'),
- self.filesystem.splitdrive('!!foo!!bar'))
- self.assertEqual(('!!foo!bar', '!!'),
- self.filesystem.splitdrive('!!foo!bar!!'))
+ self.assertEqual(
+ ("!!foo!bar", "!baz"), self.filesystem.splitdrive("!!foo!bar!baz")
+ )
+ self.assertEqual(("", "!!foo"), self.filesystem.splitdrive("!!foo"))
+ self.assertEqual(("", "!!foo!!bar"), self.filesystem.splitdrive("!!foo!!bar"))
+ self.assertEqual(("!!foo!bar", "!!"), self.filesystem.splitdrive("!!foo!bar!!"))
def test_split_drive_with_unc_path_alt_sep(self):
- self.assertEqual(('^^foo^bar', '!baz'),
- self.filesystem.splitdrive('^^foo^bar!baz'))
- self.assertEqual(('', '^^foo'), self.filesystem.splitdrive('^^foo'))
- self.assertEqual(('', '^^foo^^bar'),
- self.filesystem.splitdrive('^^foo^^bar'))
- self.assertEqual(('^^foo^bar', '^^'),
- self.filesystem.splitdrive('^^foo^bar^^'))
+ self.assertEqual(
+ ("^^foo^bar", "!baz"), self.filesystem.splitdrive("^^foo^bar!baz")
+ )
+ self.assertEqual(("", "^^foo"), self.filesystem.splitdrive("^^foo"))
+ self.assertEqual(("", "^^foo^^bar"), self.filesystem.splitdrive("^^foo^^bar"))
+ self.assertEqual(("^^foo^bar", "^^"), self.filesystem.splitdrive("^^foo^bar^^"))
def test_split_path_with_drive(self):
- self.assertEqual(('d:!foo', 'baz'),
- self.filesystem.splitpath('d:!foo!baz'))
- self.assertEqual(('d:!foo!baz', ''),
- self.filesystem.splitpath('d:!foo!baz!'))
- self.assertEqual(('c:', ''),
- self.filesystem.splitpath('c:'))
- self.assertEqual(('c:!', ''),
- self.filesystem.splitpath('c:!'))
- self.assertEqual(('c:!!', ''),
- self.filesystem.splitpath('c:!!'))
+ self.assertEqual(("d:!foo", "baz"), self.filesystem.splitpath("d:!foo!baz"))
+ self.assertEqual(("d:!foo!baz", ""), self.filesystem.splitpath("d:!foo!baz!"))
+ self.assertEqual(("c:", ""), self.filesystem.splitpath("c:"))
+ self.assertEqual(("c:!", ""), self.filesystem.splitpath("c:!"))
+ self.assertEqual(("c:!!", ""), self.filesystem.splitpath("c:!!"))
def test_split_path_with_drive_alt_sep(self):
- self.assertEqual(('d:^foo', 'baz'),
- self.filesystem.splitpath('d:^foo^baz'))
- self.assertEqual(('d:^foo^baz', ''),
- self.filesystem.splitpath('d:^foo^baz^'))
- self.assertEqual(('c:', ''),
- self.filesystem.splitpath('c:'))
- self.assertEqual(('c:^', ''),
- self.filesystem.splitpath('c:^'))
- self.assertEqual(('c:^^', ''),
- self.filesystem.splitpath('c:^^'))
+ self.assertEqual(("d:^foo", "baz"), self.filesystem.splitpath("d:^foo^baz"))
+ self.assertEqual(("d:^foo^baz", ""), self.filesystem.splitpath("d:^foo^baz^"))
+ self.assertEqual(("c:", ""), self.filesystem.splitpath("c:"))
+ self.assertEqual(("c:^", ""), self.filesystem.splitpath("c:^"))
+ self.assertEqual(("c:^^", ""), self.filesystem.splitpath("c:^^"))
def test_split_path_with_unc_path(self):
- self.assertEqual(('!!foo!bar!', 'baz'),
- self.filesystem.splitpath('!!foo!bar!baz'))
- self.assertEqual(('!!foo!bar', ''),
- self.filesystem.splitpath('!!foo!bar'))
- self.assertEqual(('!!foo!bar!!', ''),
- self.filesystem.splitpath('!!foo!bar!!'))
+ self.assertEqual(
+ ("!!foo!bar!", "baz"), self.filesystem.splitpath("!!foo!bar!baz")
+ )
+ self.assertEqual(("!!foo!bar", ""), self.filesystem.splitpath("!!foo!bar"))
+ self.assertEqual(("!!foo!bar!!", ""), self.filesystem.splitpath("!!foo!bar!!"))
def test_split_path_with_unc_path_alt_sep(self):
- self.assertEqual(('^^foo^bar^', 'baz'),
- self.filesystem.splitpath('^^foo^bar^baz'))
- self.assertEqual(('^^foo^bar', ''),
- self.filesystem.splitpath('^^foo^bar'))
- self.assertEqual(('^^foo^bar^^', ''),
- self.filesystem.splitpath('^^foo^bar^^'))
+ self.assertEqual(
+ ("^^foo^bar^", "baz"), self.filesystem.splitpath("^^foo^bar^baz")
+ )
+ self.assertEqual(("^^foo^bar", ""), self.filesystem.splitpath("^^foo^bar"))
+ self.assertEqual(("^^foo^bar^^", ""), self.filesystem.splitpath("^^foo^bar^^"))
+
+ def test_splitroot_with_drive(self):
+ self.assertEqual(
+ ("E:", "!", "foo!bar"), self.filesystem.splitroot("E:!foo!bar")
+ )
+ self.assertEqual(
+ ("E:", "!", "!foo!!!bar"), self.filesystem.splitroot("E:!!foo!!!bar")
+ )
+ self.assertEqual(
+ (b"E:", b"!", b"!foo!!!bar"), self.filesystem.splitroot(b"E:!!foo!!!bar")
+ )
+ self.assertEqual(
+ ("C:", "^", "foo^bar"), self.filesystem.splitroot("C:^foo^bar")
+ )
+
+ def test_splitroot_with_unc_path(self):
+ self.assertEqual(
+ ("!!foo!bar", "!", "baz"), self.filesystem.splitroot("!!foo!bar!baz")
+ )
+ self.assertEqual(
+ ("!!?!UNC", "!", "foo!bar"), self.filesystem.splitroot("!!?!UNC!foo!bar")
+ )
+ self.assertEqual(
+ ("^^foo^bar", "^", "baz"), self.filesystem.splitroot("^^foo^bar^baz")
+ )
+ self.assertEqual(
+ (b"!!foo!bar", b"!", b"baz"), self.filesystem.splitroot(b"!!foo!bar!baz")
+ )
+
+ def test_splitroot_with_empty_parts(self):
+ self.assertEqual(("", "", ""), self.filesystem.splitroot(""))
+ self.assertEqual(("", "!", "foo"), self.filesystem.splitroot("!foo"))
+ self.assertEqual(("!!foo!bar", "", ""), self.filesystem.splitroot("!!foo!bar"))
+ self.assertEqual(("!!foo", "", ""), self.filesystem.splitroot("!!foo"))
+ self.assertEqual(
+ ("!!foo!bar", "!", ""), self.filesystem.splitroot("!!foo!bar!")
+ )
+ self.assertEqual(("C:", "", "foo!bar"), self.filesystem.splitroot("C:foo!bar"))
class DiskSpaceTest(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='!',
- total_size=100)
- self.os = fake_filesystem.FakeOsModule(self.filesystem)
- self.open = fake_filesystem.FakeFileOpen(self.filesystem)
+ self.fs = fake_filesystem.FakeFilesystem(path_separator="!", total_size=100)
+ self.os = fake_os.FakeOsModule(self.fs)
+ self.open = fake_open.FakeFileOpen(self.fs)
def test_disk_usage_on_file_creation(self):
total_size = 100
- self.filesystem.add_mount_point('mount', total_size)
+ self.fs.add_mount_point("!mount", total_size)
def create_too_large_file():
- with self.open('!mount!file', 'w') as dest:
- dest.write('a' * (total_size + 1))
+ with self.open("!mount!file", "w") as dest:
+ dest.write("a" * (total_size + 1))
with self.assertRaises(OSError):
create_too_large_file()
- self.assertEqual(0, self.filesystem.get_disk_usage('!mount').used)
+ self.assertEqual(0, self.fs.get_disk_usage("!mount").used)
+
+ with self.open("!mount!file", "w") as dest:
+ dest.write("a" * total_size)
- with self.open('!mount!file', 'w') as dest:
- dest.write('a' * total_size)
+ self.assertEqual(total_size, self.fs.get_disk_usage("!mount").used)
- self.assertEqual(total_size,
- self.filesystem.get_disk_usage('!mount').used)
+ def test_disk_usage_on_automounted_drive(self):
+ self.fs.is_windows_fs = True
+ self.fs.reset(total_size=100)
+ self.fs.create_file("!foo!bar", st_size=50)
+ self.assertEqual(0, self.fs.get_disk_usage("D:!").used)
+ self.fs.cwd = "E:!foo"
+ self.assertEqual(0, self.fs.get_disk_usage("!foo").used)
+
+ def test_disk_usage_on_mounted_paths(self):
+ self.fs.add_mount_point("!foo", total_size=200)
+ self.fs.add_mount_point("!foo!bar", total_size=400)
+ self.fs.create_file("!baz", st_size=50)
+ self.fs.create_file("!foo!baz", st_size=60)
+ self.fs.create_file("!foo!bar!baz", st_size=100)
+ self.assertEqual(50, self.fs.get_disk_usage("!").used)
+ self.assertEqual(60, self.fs.get_disk_usage("!foo").used)
+ self.assertEqual(100, self.fs.get_disk_usage("!foo!bar").used)
+ self.assertEqual(400, self.fs.get_disk_usage("!foo!bar").total)
def test_file_system_size_after_large_file_creation(self):
filesystem = fake_filesystem.FakeFilesystem(
- path_separator='!', total_size=1024 * 1024 * 1024 * 100)
- filesystem.create_file('!foo!baz', st_size=1024 * 1024 * 1024 * 10)
- self.assertEqual((1024 * 1024 * 1024 * 100,
- 1024 * 1024 * 1024 * 10,
- 1024 * 1024 * 1024 * 90),
- filesystem.get_disk_usage())
+ path_separator="!", total_size=1024 * 1024 * 1024 * 100
+ )
+ filesystem.create_file("!foo!baz", st_size=1024 * 1024 * 1024 * 10)
+ self.assertEqual(
+ (
+ 1024 * 1024 * 1024 * 100,
+ 1024 * 1024 * 1024 * 10,
+ 1024 * 1024 * 1024 * 90,
+ ),
+ filesystem.get_disk_usage(),
+ )
def test_file_system_size_after_binary_file_creation(self):
- self.filesystem.create_file('!foo!bar', contents=b'xyzzy')
- self.assertEqual((100, 5, 95), self.filesystem.get_disk_usage())
+ self.fs.create_file("!foo!bar", contents=b"xyzzy")
+ self.assertEqual((100, 5, 95), self.fs.get_disk_usage())
def test_file_system_size_after_ascii_string_file_creation(self):
- self.filesystem.create_file('!foo!bar', contents='complicated')
- self.assertEqual((100, 11, 89), self.filesystem.get_disk_usage())
+ self.fs.create_file("!foo!bar", contents="complicated")
+ self.assertEqual((100, 11, 89), self.fs.get_disk_usage())
def test_filesystem_size_after_2byte_unicode_file_creation(self):
- self.filesystem.create_file('!foo!bar', contents='сложно',
- encoding='utf-8')
- self.assertEqual((100, 12, 88), self.filesystem.get_disk_usage())
+ self.fs.create_file("!foo!bar", contents="сложно", encoding="utf-8")
+ self.assertEqual((100, 12, 88), self.fs.get_disk_usage())
def test_filesystem_size_after_3byte_unicode_file_creation(self):
- self.filesystem.create_file('!foo!bar', contents='複雑',
- encoding='utf-8')
- self.assertEqual((100, 6, 94), self.filesystem.get_disk_usage())
+ self.fs.create_file("!foo!bar", contents="複雑", encoding="utf-8")
+ self.assertEqual((100, 6, 94), self.fs.get_disk_usage())
def test_file_system_size_after_file_deletion(self):
- self.filesystem.create_file('!foo!bar', contents=b'xyzzy')
- self.filesystem.create_file('!foo!baz', st_size=20)
- self.filesystem.remove_object('!foo!bar')
- self.assertEqual((100, 20, 80), self.filesystem.get_disk_usage())
+ self.fs.create_file("!foo!bar", contents=b"xyzzy")
+ self.fs.create_file("!foo!baz", st_size=20)
+ self.fs.remove_object("!foo!bar")
+ self.assertEqual((100, 20, 80), self.fs.get_disk_usage())
def test_file_system_size_after_directory_removal(self):
- self.filesystem.create_file('!foo!bar', st_size=10)
- self.filesystem.create_file('!foo!baz', st_size=20)
- self.filesystem.create_file('!foo1!bar', st_size=40)
- self.filesystem.remove_object('!foo')
- self.assertEqual((100, 40, 60), self.filesystem.get_disk_usage())
+ self.fs.create_file("!foo!bar", st_size=10)
+ self.fs.create_file("!foo!baz", st_size=20)
+ self.fs.create_file("!foo1!bar", st_size=40)
+ self.fs.remove_object("!foo")
+ self.assertEqual((100, 40, 60), self.fs.get_disk_usage())
def test_creating_file_with_fitting_content(self):
- initial_usage = self.filesystem.get_disk_usage()
+ initial_usage = self.fs.get_disk_usage()
try:
- self.filesystem.create_file('!foo!bar', contents=b'a' * 100)
+ self.fs.create_file("!foo!bar", contents=b"a" * 100)
except OSError:
- self.fail('File with contents fitting into disk space '
- 'could not be written.')
+ self.fail(
+ "File with contents fitting into disk space " "could not be written."
+ )
- self.assertEqual(initial_usage.used + 100,
- self.filesystem.get_disk_usage().used)
+ self.assertEqual(initial_usage.used + 100, self.fs.get_disk_usage().used)
def test_creating_file_with_content_too_large(self):
def create_large_file():
- self.filesystem.create_file('!foo!bar', contents=b'a' * 101)
+ self.fs.create_file("!foo!bar", contents=b"a" * 101)
- initial_usage = self.filesystem.get_disk_usage()
+ initial_usage = self.fs.get_disk_usage()
with self.assertRaises(OSError):
create_large_file()
- self.assertEqual(initial_usage, self.filesystem.get_disk_usage())
+ self.assertEqual(initial_usage, self.fs.get_disk_usage())
def test_creating_file_with_fitting_size(self):
- initial_usage = self.filesystem.get_disk_usage()
+ initial_usage = self.fs.get_disk_usage()
try:
- self.filesystem.create_file('!foo!bar', st_size=100)
+ self.fs.create_file("!foo!bar", st_size=100)
except OSError:
- self.fail(
- 'File with size fitting into disk space could not be written.')
+ self.fail("File with size fitting into disk space could not be written.")
- self.assertEqual(initial_usage.used + 100,
- self.filesystem.get_disk_usage().used)
+ self.assertEqual(initial_usage.used + 100, self.fs.get_disk_usage().used)
def test_creating_file_with_size_too_large(self):
- initial_usage = self.filesystem.get_disk_usage()
+ initial_usage = self.fs.get_disk_usage()
def create_large_file():
- self.filesystem.create_file('!foo!bar', st_size=101)
+ self.fs.create_file("!foo!bar", st_size=101)
with self.assertRaises(OSError):
create_large_file()
- self.assertEqual(initial_usage, self.filesystem.get_disk_usage())
+ self.assertEqual(initial_usage, self.fs.get_disk_usage())
def test_resize_file_with_fitting_size(self):
- file_object = self.filesystem.create_file('!foo!bar', st_size=50)
+ file_object = self.fs.create_file("!foo!bar", st_size=50)
try:
file_object.set_large_file_size(100)
- file_object.set_contents(b'a' * 100)
+ file_object.set_contents(b"a" * 100)
except OSError:
- self.fail(
- 'Resizing file failed although disk space was sufficient.')
+ self.fail("Resizing file failed although disk space was sufficient.")
def test_resize_file_with_size_too_large(self):
- file_object = self.filesystem.create_file('!foo!bar', st_size=50)
+ file_object = self.fs.create_file("!foo!bar", st_size=50)
with self.raises_os_error(errno.ENOSPC):
file_object.set_large_file_size(200)
with self.raises_os_error(errno.ENOSPC):
- file_object.set_contents('a' * 150)
+ file_object.set_contents("a" * 150)
def test_file_system_size_after_directory_rename(self):
- self.filesystem.create_file('!foo!bar', st_size=20)
- self.os.rename('!foo', '!baz')
- self.assertEqual(20, self.filesystem.get_disk_usage().used)
+ self.fs.create_file("!foo!bar", st_size=20)
+ self.os.rename("!foo", "!baz")
+ self.assertEqual(20, self.fs.get_disk_usage().used)
def test_file_system_size_after_file_rename(self):
- self.filesystem.create_file('!foo!bar', st_size=20)
- self.os.rename('!foo!bar', '!foo!baz')
- self.assertEqual(20, self.filesystem.get_disk_usage().used)
+ self.fs.create_file("!foo!bar", st_size=20)
+ self.os.rename("!foo!bar", "!foo!baz")
+ self.assertEqual(20, self.fs.get_disk_usage().used)
def test_that_hard_link_does_not_change_used_size(self):
- file1_path = 'test_file1'
- file2_path = 'test_file2'
- self.filesystem.create_file(file1_path, st_size=20)
- self.assertEqual(20, self.filesystem.get_disk_usage().used)
+ file1_path = "test_file1"
+ file2_path = "test_file2"
+ self.fs.create_file(file1_path, st_size=20)
+ self.assertEqual(20, self.fs.get_disk_usage().used)
# creating a hard link shall not increase used space
self.os.link(file1_path, file2_path)
- self.assertEqual(20, self.filesystem.get_disk_usage().used)
+ self.assertEqual(20, self.fs.get_disk_usage().used)
# removing a file shall not decrease used space
# if a hard link still exists
self.os.unlink(file1_path)
- self.assertEqual(20, self.filesystem.get_disk_usage().used)
+ self.assertEqual(20, self.fs.get_disk_usage().used)
self.os.unlink(file2_path)
- self.assertEqual(0, self.filesystem.get_disk_usage().used)
+ self.assertEqual(0, self.fs.get_disk_usage().used)
def test_that_the_size_of_correct_mount_point_is_used(self):
- self.filesystem.add_mount_point('!mount_limited', total_size=50)
- self.filesystem.add_mount_point('!mount_unlimited')
+ self.fs.add_mount_point("!mount_limited", total_size=50)
+ self.fs.add_mount_point("!mount_unlimited")
with self.raises_os_error(errno.ENOSPC):
- self.filesystem.create_file('!mount_limited!foo', st_size=60)
+ self.fs.create_file("!mount_limited!foo", st_size=60)
with self.raises_os_error(errno.ENOSPC):
- self.filesystem.create_file('!bar', st_size=110)
+ self.fs.create_file("!bar", st_size=110)
try:
- self.filesystem.create_file('!foo', st_size=60)
- self.filesystem.create_file('!mount_limited!foo', st_size=40)
- self.filesystem.create_file('!mount_unlimited!foo',
- st_size=1000000)
+ self.fs.create_file("!foo", st_size=60)
+ self.fs.create_file("!mount_limited!foo", st_size=40)
+ self.fs.create_file("!mount_unlimited!foo", st_size=1000000)
except OSError:
- self.fail('File with contents fitting into '
- 'disk space could not be written.')
+ self.fail(
+ "File with contents fitting into " "disk space could not be written."
+ )
def test_that_disk_usage_of_correct_mount_point_is_used(self):
- self.filesystem.add_mount_point('!mount1', total_size=20)
- self.filesystem.add_mount_point('!mount1!bar!mount2', total_size=50)
+ self.fs.add_mount_point("!mount1", total_size=20)
+ self.fs.add_mount_point("!mount1!bar!mount2", total_size=50)
- self.filesystem.create_file('!foo!bar', st_size=10)
- self.filesystem.create_file('!mount1!foo!bar', st_size=10)
- self.filesystem.create_file('!mount1!bar!mount2!foo!bar', st_size=10)
+ self.fs.create_file("!foo!bar", st_size=10)
+ self.fs.create_file("!mount1!foo!bar", st_size=10)
+ self.fs.create_file("!mount1!bar!mount2!foo!bar", st_size=10)
- self.assertEqual(90, self.filesystem.get_disk_usage('!foo').free)
- self.assertEqual(10,
- self.filesystem.get_disk_usage('!mount1!foo').free)
- self.assertEqual(40, self.filesystem.get_disk_usage(
- '!mount1!bar!mount2').free)
+ self.assertEqual(90, self.fs.get_disk_usage("!foo").free)
+ self.assertEqual(10, self.fs.get_disk_usage("!mount1!foo").free)
+ self.assertEqual(40, self.fs.get_disk_usage("!mount1!bar!mount2").free)
def test_set_larger_disk_size(self):
- self.filesystem.add_mount_point('!mount1', total_size=20)
+ self.fs.add_mount_point("!mount1", total_size=20)
with self.raises_os_error(errno.ENOSPC):
- self.filesystem.create_file('!mount1!foo', st_size=100)
- self.filesystem.set_disk_usage(total_size=200, path='!mount1')
- self.filesystem.create_file('!mount1!foo', st_size=100)
- self.assertEqual(100,
- self.filesystem.get_disk_usage('!mount1!foo').free)
+ self.fs.create_file("!mount1!foo", st_size=100)
+ self.fs.set_disk_usage(total_size=200, path="!mount1")
+ self.fs.create_file("!mount1!foo", st_size=100)
+ self.assertEqual(100, self.fs.get_disk_usage("!mount1!foo").free)
def test_set_smaller_disk_size(self):
- self.filesystem.add_mount_point('!mount1', total_size=200)
- self.filesystem.create_file('!mount1!foo', st_size=100)
+ self.fs.add_mount_point("!mount1", total_size=200)
+ self.fs.create_file("!mount1!foo", st_size=100)
with self.raises_os_error(errno.ENOSPC):
- self.filesystem.set_disk_usage(total_size=50, path='!mount1')
- self.filesystem.set_disk_usage(total_size=150, path='!mount1')
- self.assertEqual(50,
- self.filesystem.get_disk_usage('!mount1!foo').free)
+ self.fs.set_disk_usage(total_size=50, path="!mount1")
+ self.fs.set_disk_usage(total_size=150, path="!mount1")
+ self.assertEqual(50, self.fs.get_disk_usage("!mount1!foo").free)
def test_disk_size_on_unlimited_disk(self):
- self.filesystem.add_mount_point('!mount1')
- self.filesystem.create_file('!mount1!foo', st_size=100)
- self.filesystem.set_disk_usage(total_size=1000, path='!mount1')
- self.assertEqual(900,
- self.filesystem.get_disk_usage('!mount1!foo').free)
+ self.fs.add_mount_point("!mount1")
+ self.fs.create_file("!mount1!foo", st_size=100)
+ self.fs.set_disk_usage(total_size=1000, path="!mount1")
+ self.assertEqual(900, self.fs.get_disk_usage("!mount1!foo").free)
def test_disk_size_on_auto_mounted_drive_on_file_creation(self):
- self.filesystem.is_windows_fs = True
+ self.fs.is_windows_fs = True
# drive d: shall be auto-mounted and the used size adapted
- self.filesystem.create_file('d:!foo!bar', st_size=100)
- self.filesystem.set_disk_usage(total_size=1000, path='d:')
- self.assertEqual(self.filesystem.get_disk_usage('d:!foo').free, 900)
+ self.fs.create_file("d:!foo!bar", st_size=100)
+ self.fs.set_disk_usage(total_size=1000, path="d:")
+ self.assertEqual(self.fs.get_disk_usage("d:!foo").free, 900)
def test_disk_size_on_auto_mounted_drive_on_directory_creation(self):
- self.filesystem.is_windows_fs = True
- self.filesystem.create_dir('d:!foo!bar')
- self.filesystem.create_file('d:!foo!bar!baz', st_size=100)
- self.filesystem.create_file('d:!foo!baz', st_size=100)
- self.filesystem.set_disk_usage(total_size=1000, path='d:')
- self.assertEqual(800, self.filesystem.get_disk_usage('d:!foo').free)
+ self.fs.is_windows_fs = True
+ self.fs.create_dir("d:!foo!bar")
+ self.fs.create_file("d:!foo!bar!baz", st_size=100)
+ self.fs.create_file("d:!foo!baz", st_size=100)
+ self.fs.set_disk_usage(total_size=1000, path="d:")
+ self.assertEqual(800, self.fs.get_disk_usage("d:!foo").free)
def test_copying_preserves_byte_contents(self):
- source_file = self.filesystem.create_file('foo', contents=b'somebytes')
- dest_file = self.filesystem.create_file('bar')
+ source_file = self.fs.create_file("foo", contents=b"somebytes")
+ dest_file = self.fs.create_file("bar")
dest_file.set_contents(source_file.contents)
self.assertEqual(dest_file.contents, source_file.contents)
def test_diskusage_after_open_write(self):
- with self.open('bar.txt', 'w') as f:
- f.write('a' * 60)
+ with self.open("bar.txt", "w") as f:
+ f.write("a" * 60)
f.flush()
- self.assertEqual(60, self.filesystem.get_disk_usage()[1])
+ self.assertEqual(60, self.fs.get_disk_usage()[1])
def test_disk_full_after_reopened(self):
- with self.open('bar.txt', 'w') as f:
- f.write('a' * 60)
- with self.open('bar.txt') as f:
- self.assertEqual('a' * 60, f.read())
+ with self.open("bar.txt", "w") as f:
+ f.write("a" * 60)
+ with self.open("bar.txt") as f:
+ self.assertEqual("a" * 60, f.read())
with self.raises_os_error(errno.ENOSPC):
- with self.open('bar.txt', 'w') as f:
- f.write('b' * 110)
+ with self.open("bar.txt", "w") as f:
+ f.write("b" * 110)
with self.raises_os_error(errno.ENOSPC):
f.flush()
- with self.open('bar.txt') as f:
- self.assertEqual('', f.read())
+ with self.open("bar.txt") as f:
+ self.assertEqual("", f.read())
def test_disk_full_append(self):
- file_path = 'bar.txt'
- with self.open(file_path, 'w') as f:
- f.write('a' * 60)
+ file_path = "bar.txt"
+ with self.open(file_path, "w") as f:
+ f.write("a" * 60)
with self.open(file_path) as f:
- self.assertEqual('a' * 60, f.read())
+ self.assertEqual("a" * 60, f.read())
with self.raises_os_error(errno.ENOSPC):
- with self.open(file_path, 'a') as f:
- f.write('b' * 41)
+ with self.open(file_path, "a") as f:
+ f.write("b" * 41)
with self.raises_os_error(errno.ENOSPC):
f.flush()
- with self.open('bar.txt') as f:
- self.assertEqual(f.read(), 'a' * 60)
+ with self.open("bar.txt") as f:
+ self.assertEqual(f.read(), "a" * 60)
def test_disk_full_after_reopened_rplus_seek(self):
- with self.open('bar.txt', 'w') as f:
- f.write('a' * 60)
- with self.open('bar.txt') as f:
- self.assertEqual(f.read(), 'a' * 60)
+ with self.open("bar.txt", "w") as f:
+ f.write("a" * 60)
+ with self.open("bar.txt") as f:
+ self.assertEqual(f.read(), "a" * 60)
with self.raises_os_error(errno.ENOSPC):
- with self.open('bar.txt', 'r+') as f:
+ with self.open("bar.txt", "r+") as f:
f.seek(50)
- f.write('b' * 60)
+ f.write("b" * 60)
with self.raises_os_error(errno.ENOSPC):
f.flush()
- with self.open('bar.txt') as f:
- self.assertEqual(f.read(), 'a' * 60)
+ with self.open("bar.txt") as f:
+ self.assertEqual(f.read(), "a" * 60)
class MountPointTest(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='!',
- total_size=100)
- self.filesystem.add_mount_point('!foo')
- self.filesystem.add_mount_point('!bar')
- self.filesystem.add_mount_point('!foo!baz')
+ self.filesystem = fake_filesystem.FakeFilesystem(
+ path_separator="!", total_size=100
+ )
+
+ def add_mount_points(self):
+ self.filesystem.add_mount_point("!foo")
+ self.filesystem.add_mount_point("!bar")
+ self.filesystem.add_mount_point("!foo!baz")
def test_that_new_mount_points_get_new_device_number(self):
- self.assertEqual(1, self.filesystem.get_object('!').st_dev)
- self.assertEqual(2, self.filesystem.get_object('!foo').st_dev)
- self.assertEqual(3, self.filesystem.get_object('!bar').st_dev)
- self.assertEqual(4, self.filesystem.get_object('!foo!baz').st_dev)
+ self.add_mount_points()
+ self.assertEqual(1, self.filesystem.get_object("!").st_dev)
+ self.assertEqual(2, self.filesystem.get_object("!foo").st_dev)
+ self.assertEqual(3, self.filesystem.get_object("!bar").st_dev)
+ self.assertEqual(4, self.filesystem.get_object("!foo!baz").st_dev)
def test_that_new_directories_get_correct_device_number(self):
- self.assertEqual(1, self.filesystem.create_dir('!foo1!bar').st_dev)
- self.assertEqual(2, self.filesystem.create_dir('!foo!bar').st_dev)
- self.assertEqual(4,
- self.filesystem.create_dir('!foo!baz!foo!bar').st_dev)
+ self.add_mount_points()
+ self.assertEqual(1, self.filesystem.create_dir("!foo1!bar").st_dev)
+ self.assertEqual(2, self.filesystem.create_dir("!foo!bar").st_dev)
+ self.assertEqual(4, self.filesystem.create_dir("!foo!baz!foo!bar").st_dev)
def test_that_new_files_get_correct_device_number(self):
- self.assertEqual(1, self.filesystem.create_file('!foo1!bar').st_dev)
- self.assertEqual(2, self.filesystem.create_file('!foo!bar').st_dev)
- self.assertEqual(4, self.filesystem.create_file(
- '!foo!baz!foo!bar').st_dev)
+ self.add_mount_points()
+ self.assertEqual(1, self.filesystem.create_file("!foo1!bar").st_dev)
+ self.assertEqual(2, self.filesystem.create_file("!foo!bar").st_dev)
+ self.assertEqual(4, self.filesystem.create_file("!foo!baz!foo!bar").st_dev)
def test_that_mount_point_cannot_be_added_twice(self):
+ self.add_mount_points()
with self.raises_os_error(errno.EEXIST):
- self.filesystem.add_mount_point('!foo')
+ self.filesystem.add_mount_point("!foo")
with self.raises_os_error(errno.EEXIST):
- self.filesystem.add_mount_point('!foo!')
+ self.filesystem.add_mount_point("!foo!")
def test_that_drives_are_auto_mounted(self):
self.filesystem.is_windows_fs = True
- self.filesystem.create_dir('d:!foo!bar')
- self.filesystem.create_file('d:!foo!baz')
- self.filesystem.create_file('z:!foo!baz')
- self.assertEqual(5, self.filesystem.get_object('d:').st_dev)
- self.assertEqual(5, self.filesystem.get_object('d:!foo!bar').st_dev)
- self.assertEqual(5, self.filesystem.get_object('d:!foo!baz').st_dev)
- self.assertEqual(6, self.filesystem.get_object('z:!foo!baz').st_dev)
+ self.add_mount_points()
+ self.filesystem.create_dir("d:!foo!bar")
+ self.filesystem.create_file("d:!foo!baz")
+ self.filesystem.create_file("z:!foo!baz")
+ self.assertEqual(5, self.filesystem.get_object("d:").st_dev)
+ self.assertEqual(5, self.filesystem.get_object("d:!foo!bar").st_dev)
+ self.assertEqual(5, self.filesystem.get_object("d:!foo!baz").st_dev)
+ self.assertEqual(6, self.filesystem.get_object("z:!foo!baz").st_dev)
def test_that_drives_are_auto_mounted_case_insensitive(self):
self.filesystem.is_windows_fs = True
+ self.add_mount_points()
self.filesystem.is_case_sensitive = False
- self.filesystem.create_dir('D:!foo!bar')
- self.filesystem.create_file('e:!foo!baz')
- self.assertEqual(5, self.filesystem.get_object('D:').st_dev)
- self.assertEqual(5, self.filesystem.get_object('d:!foo!bar').st_dev)
- self.assertEqual(6, self.filesystem.get_object('e:!foo').st_dev)
- self.assertEqual(6, self.filesystem.get_object('E:!Foo!Baz').st_dev)
+ self.filesystem.create_dir("D:!foo!bar")
+ self.filesystem.create_file("e:!foo!baz")
+ self.assertEqual(5, self.filesystem.get_object("D:").st_dev)
+ self.assertEqual(5, self.filesystem.get_object("d:!foo!bar").st_dev)
+ self.assertEqual(6, self.filesystem.get_object("e:!foo").st_dev)
+ self.assertEqual(6, self.filesystem.get_object("E:!Foo!Baz").st_dev)
def test_that_unc_paths_are_auto_mounted(self):
self.filesystem.is_windows_fs = True
- self.filesystem.create_dir('!!foo!bar!baz')
- self.filesystem.create_file('!!foo!bar!bip!bop')
- self.assertEqual(5, self.filesystem.get_object('!!foo!bar').st_dev)
- self.assertEqual(5, self.filesystem.get_object(
- '!!foo!bar!bip!bop').st_dev)
+ self.add_mount_points()
+ self.filesystem.create_dir("!!foo!bar!baz")
+ self.filesystem.create_file("!!foo!bar!bip!bop")
+ self.assertEqual(5, self.filesystem.get_object("!!foo!bar").st_dev)
+ self.assertEqual(5, self.filesystem.get_object("!!foo!bar!bip!bop").st_dev)
class ConvenienceMethodTest(RealFsTestCase):
-
def test_create_link_with_non_existent_parent(self):
self.skip_if_symlink_not_supported()
- file1_path = self.make_path('test_file1')
- link_path = self.make_path('nonexistent', 'test_file2')
+ file1_path = self.make_path("test_file1")
+ link_path = self.make_path("nonexistent", "test_file2")
- self.filesystem.create_file(file1_path, contents='link test')
+ self.filesystem.create_file(file1_path, contents="link test")
self.assertEqual(self.os.stat(file1_path).st_nlink, 1)
self.filesystem.create_link(file1_path, link_path)
self.assertEqual(self.os.stat(file1_path).st_nlink, 2)
@@ -1922,10 +2007,10 @@ class ConvenienceMethodTest(RealFsTestCase):
def test_create_symlink_with_non_existent_parent(self):
self.skip_if_symlink_not_supported()
- file1_path = self.make_path('test_file1')
- link_path = self.make_path('nonexistent', 'test_file2')
+ file1_path = self.make_path("test_file1")
+ link_path = self.make_path("nonexistent", "test_file2")
- self.filesystem.create_file(file1_path, contents='symlink test')
+ self.filesystem.create_file(file1_path, contents="symlink test")
self.filesystem.create_symlink(link_path, file1_path)
self.assertTrue(self.filesystem.exists(link_path))
self.assertTrue(self.filesystem.islink(link_path))
@@ -1936,18 +2021,19 @@ class RealFileSystemAccessTest(RealFsTestCase):
# use the real path separator to work with the real file system
self.filesystem = fake_filesystem.FakeFilesystem()
self.fake_open = fake_filesystem.FakeFileOpen(self.filesystem)
- self.pyfakefs_path = os.path.split(
- os.path.dirname(os.path.abspath(__file__)))[0]
+ self.pyfakefs_path = os.path.split(os.path.dirname(os.path.abspath(__file__)))[
+ 0
+ ]
self.root_path = os.path.split(self.pyfakefs_path)[0]
def test_add_non_existing_real_file_raises(self):
- nonexisting_path = os.path.join('nonexisting', 'test.txt')
+ nonexisting_path = os.path.join("nonexisting", "test.txt")
with self.assertRaises(OSError):
self.filesystem.add_real_file(nonexisting_path)
self.assertFalse(self.filesystem.exists(nonexisting_path))
def test_add_non_existing_real_directory_raises(self):
- nonexisting_path = '/nonexisting'
+ nonexisting_path = "/nonexisting"
with self.raises_os_error(errno.ENOENT):
self.filesystem.add_real_directory(nonexisting_path)
self.assertFalse(self.filesystem.exists(nonexisting_path))
@@ -1963,8 +2049,7 @@ class RealFileSystemAccessTest(RealFsTestCase):
with self.raises_os_error(errno.EEXIST):
self.filesystem.add_real_directory(self.root_path)
- def check_fake_file_stat(self, fake_file, real_file_path,
- target_path=None):
+ def check_fake_file_stat(self, fake_file, real_file_path, target_path=None):
if target_path is None or target_path == real_file_path:
self.assertTrue(self.filesystem.exists(real_file_path))
else:
@@ -1974,38 +2059,35 @@ class RealFileSystemAccessTest(RealFsTestCase):
real_stat = os.stat(real_file_path)
self.assertIsNone(fake_file._byte_contents)
self.assertEqual(fake_file.st_size, real_stat.st_size)
- self.assertAlmostEqual(fake_file.st_ctime, real_stat.st_ctime,
- places=5)
- self.assertAlmostEqual(fake_file.st_atime, real_stat.st_atime,
- places=5)
- self.assertAlmostEqual(fake_file.st_mtime, real_stat.st_mtime,
- places=5)
+ self.assertAlmostEqual(fake_file.st_ctime, real_stat.st_ctime, places=5)
+ self.assertAlmostEqual(fake_file.st_atime, real_stat.st_atime, places=5)
+ self.assertAlmostEqual(fake_file.st_mtime, real_stat.st_mtime, places=5)
self.assertEqual(fake_file.st_uid, real_stat.st_uid)
self.assertEqual(fake_file.st_gid, real_stat.st_gid)
def check_read_only_file(self, fake_file, real_file_path):
- with open(real_file_path, 'rb') as f:
+ with open(real_file_path, "rb") as f:
real_contents = f.read()
self.assertEqual(fake_file.byte_contents, real_contents)
if not is_root():
with self.raises_os_error(errno.EACCES):
- self.fake_open(real_file_path, 'w')
+ self.fake_open(real_file_path, "w")
else:
- with self.fake_open(real_file_path, 'w'):
+ with self.fake_open(real_file_path, "w"):
pass
def check_writable_file(self, fake_file, real_file_path):
- with open(real_file_path, 'rb') as f:
+ with open(real_file_path, "rb") as f:
real_contents = f.read()
self.assertEqual(fake_file.byte_contents, real_contents)
- with self.fake_open(real_file_path, 'wb') as f:
- f.write(b'test')
- with open(real_file_path, 'rb') as f:
+ with self.fake_open(real_file_path, "wb") as f:
+ f.write(b"test")
+ with open(real_file_path, "rb") as f:
real_contents1 = f.read()
self.assertEqual(real_contents1, real_contents)
- with self.fake_open(real_file_path, 'rb') as f:
+ with self.fake_open(real_file_path, "rb") as f:
fake_contents = f.read()
- self.assertEqual(fake_contents, b'test')
+ self.assertEqual(fake_contents, b"test")
def test_add_existing_real_file_read_only(self):
real_file_path = os.path.abspath(__file__)
@@ -2016,8 +2098,7 @@ class RealFileSystemAccessTest(RealFsTestCase):
def test_add_existing_real_file_read_write(self):
real_file_path = os.path.realpath(__file__)
- fake_file = self.filesystem.add_real_file(real_file_path,
- read_only=False)
+ fake_file = self.filesystem.add_real_file(real_file_path, read_only=False)
self.check_fake_file_stat(fake_file, real_file_path)
self.assertEqual(fake_file.st_mode, os.stat(real_file_path).st_mode)
@@ -2025,38 +2106,40 @@ class RealFileSystemAccessTest(RealFsTestCase):
def test_add_real_file_to_existing_path(self):
real_file_path = os.path.abspath(__file__)
- self.filesystem.create_file('/foo/bar')
+ self.filesystem.create_file("/foo/bar")
with self.raises_os_error(errno.EEXIST):
- self.filesystem.add_real_file(real_file_path,
- target_path='/foo/bar')
+ self.filesystem.add_real_file(real_file_path, target_path="/foo/bar")
def test_add_real_file_to_non_existing_path(self):
real_file_path = os.path.abspath(__file__)
- fake_file = self.filesystem.add_real_file(real_file_path,
- target_path='/foo/bar')
- self.check_fake_file_stat(fake_file, real_file_path,
- target_path='/foo/bar')
+ fake_file = self.filesystem.add_real_file(
+ real_file_path, target_path="/foo/bar"
+ )
+ self.check_fake_file_stat(fake_file, real_file_path, target_path="/foo/bar")
def test_write_to_real_file(self):
# regression test for #470
real_file_path = os.path.abspath(__file__)
self.filesystem.add_real_file(real_file_path, read_only=False)
- with self.fake_open(real_file_path, 'w') as f:
- f.write('foo')
+ with self.fake_open(real_file_path, "w") as f:
+ f.write("foo")
- with self.fake_open(real_file_path, 'rb') as f:
- self.assertEqual(b'foo', f.read())
+ with self.fake_open(real_file_path, "rb") as f:
+ self.assertEqual(b"foo", f.read())
def test_add_existing_real_directory_read_only(self):
self.filesystem.add_real_directory(self.pyfakefs_path)
self.assertTrue(self.filesystem.exists(self.pyfakefs_path))
- self.assertTrue(self.filesystem.exists(
- os.path.join(self.pyfakefs_path, 'fake_filesystem.py')))
- self.assertTrue(self.filesystem.exists(
- os.path.join(self.pyfakefs_path, 'fake_pathlib.py')))
+ self.assertTrue(
+ self.filesystem.exists(
+ os.path.join(self.pyfakefs_path, "fake_filesystem.py")
+ )
+ )
+ self.assertTrue(
+ self.filesystem.exists(os.path.join(self.pyfakefs_path, "fake_pathlib.py"))
+ )
- file_path = os.path.join(self.pyfakefs_path,
- 'fake_filesystem_shutil.py')
+ file_path = os.path.join(self.pyfakefs_path, "fake_filesystem_shutil.py")
fake_file = self.filesystem.resolve(file_path)
self.check_fake_file_stat(fake_file, file_path)
self.check_read_only_file(fake_file, file_path)
@@ -2065,15 +2148,24 @@ class RealFileSystemAccessTest(RealFsTestCase):
self.filesystem.add_real_directory(self.root_path)
self.assertTrue(
self.filesystem.exists(
- os.path.join(self.root_path, 'pyfakefs', 'tests',
- 'fake_filesystem_test.py')))
+ os.path.join(
+ self.root_path,
+ "pyfakefs",
+ "tests",
+ "fake_filesystem_test.py",
+ )
+ )
+ )
self.assertTrue(
self.filesystem.exists(
- os.path.join(self.root_path, 'pyfakefs',
- 'fake_filesystem.py')))
+ os.path.join(self.root_path, "pyfakefs", "fake_filesystem.py")
+ )
+ )
self.assertTrue(
self.filesystem.exists(
- os.path.join(self.root_path, 'pyfakefs', '__init__.py')))
+ os.path.join(self.root_path, "pyfakefs", "__init__.py")
+ )
+ )
@contextlib.contextmanager
def create_symlinks(self, symlinks):
@@ -2087,33 +2179,43 @@ class RealFileSystemAccessTest(RealFsTestCase):
def test_add_existing_real_directory_symlink(self):
fake_open = fake_filesystem.FakeFileOpen(self.filesystem)
- real_directory = os.path.join(self.root_path, 'pyfakefs', 'tests')
+ real_directory = os.path.join(self.root_path, "pyfakefs", "tests")
symlinks = [
- ('..', os.path.join(
- real_directory, 'fixtures', 'symlink_dir_relative')),
- ('../all_tests.py', os.path.join(
- real_directory, 'fixtures', 'symlink_file_relative')),
- (real_directory, os.path.join(
- real_directory, 'fixtures', 'symlink_dir_absolute')),
- (os.path.join(real_directory, 'all_tests.py'), os.path.join(
- real_directory, 'fixtures', 'symlink_file_absolute')),
- ('/etc/something', os.path.join(
- real_directory, 'fixtures', 'symlink_file_absolute_outside')),
+ (
+ "..",
+ os.path.join(real_directory, "fixtures", "symlink_dir_relative"),
+ ),
+ (
+ "../all_tests.py",
+ os.path.join(real_directory, "fixtures", "symlink_file_relative"),
+ ),
+ (
+ real_directory,
+ os.path.join(real_directory, "fixtures", "symlink_dir_absolute"),
+ ),
+ (
+ os.path.join(real_directory, "all_tests.py"),
+ os.path.join(real_directory, "fixtures", "symlink_file_absolute"),
+ ),
+ (
+ "/etc/something",
+ os.path.join(
+ real_directory, "fixtures", "symlink_file_absolute_outside"
+ ),
+ ),
]
- self.filesystem.create_file('/etc/something')
+ self.filesystem.create_file("/etc/something")
- with fake_open('/etc/something', 'w') as f:
- f.write('good morning')
+ with fake_open("/etc/something", "w") as f:
+ f.write("good morning")
try:
with self.create_symlinks(symlinks):
- self.filesystem.add_real_directory(
- real_directory, lazy_read=False)
+ self.filesystem.add_real_directory(real_directory, lazy_read=False)
except OSError:
if self.is_windows:
- raise unittest.SkipTest(
- 'Symlinks under Windows need admin privileges')
+ raise unittest.SkipTest("Symlinks under Windows need admin privileges")
raise
for link in symlinks:
@@ -2122,136 +2224,213 @@ class RealFileSystemAccessTest(RealFsTestCase):
# relative
self.assertTrue(
self.filesystem.exists(
- os.path.join(self.root_path, 'pyfakefs', 'tests',
- 'fixtures/symlink_dir_relative')))
+ os.path.join(
+ self.root_path,
+ "pyfakefs",
+ "tests",
+ "fixtures/symlink_dir_relative",
+ )
+ )
+ )
self.assertTrue(
self.filesystem.exists(
- os.path.join(self.root_path, 'pyfakefs', 'tests',
- 'fixtures/symlink_dir_relative/all_tests.py')))
+ os.path.join(
+ self.root_path,
+ "pyfakefs",
+ "tests",
+ "fixtures/symlink_dir_relative/all_tests.py",
+ )
+ )
+ )
self.assertTrue(
self.filesystem.exists(
- os.path.join(self.root_path, 'pyfakefs', 'tests',
- 'fixtures/symlink_file_relative')))
+ os.path.join(
+ self.root_path,
+ "pyfakefs",
+ "tests",
+ "fixtures/symlink_file_relative",
+ )
+ )
+ )
# absolute
self.assertTrue(
self.filesystem.exists(
- os.path.join(self.root_path, 'pyfakefs', 'tests',
- 'fixtures/symlink_dir_absolute')))
+ os.path.join(
+ self.root_path,
+ "pyfakefs",
+ "tests",
+ "fixtures/symlink_dir_absolute",
+ )
+ )
+ )
self.assertTrue(
self.filesystem.exists(
- os.path.join(self.root_path, 'pyfakefs', 'tests',
- 'fixtures/symlink_dir_absolute/all_tests.py')))
+ os.path.join(
+ self.root_path,
+ "pyfakefs",
+ "tests",
+ "fixtures/symlink_dir_absolute/all_tests.py",
+ )
+ )
+ )
self.assertTrue(
self.filesystem.exists(
- os.path.join(self.root_path, 'pyfakefs', 'tests',
- 'fixtures/symlink_file_absolute')))
+ os.path.join(
+ self.root_path,
+ "pyfakefs",
+ "tests",
+ "fixtures/symlink_file_absolute",
+ )
+ )
+ )
# outside
self.assertTrue(
self.filesystem.exists(
- os.path.join(self.root_path, 'pyfakefs', 'tests',
- 'fixtures/symlink_file_absolute_outside')))
+ os.path.join(
+ self.root_path,
+ "pyfakefs",
+ "tests",
+ "fixtures/symlink_file_absolute_outside",
+ )
+ )
+ )
self.assertEqual(
- fake_open(os.path.join(
- self.root_path, 'pyfakefs', 'tests',
- 'fixtures/symlink_file_absolute_outside')).read(),
- 'good morning'
+ fake_open(
+ os.path.join(
+ self.root_path,
+ "pyfakefs",
+ "tests",
+ "fixtures/symlink_file_absolute_outside",
+ )
+ ).read(),
+ "good morning",
)
def test_add_existing_real_directory_symlink_target_path(self):
self.skip_if_symlink_not_supported(force_real_fs=True)
- real_directory = os.path.join(self.root_path, 'pyfakefs', 'tests')
+ real_directory = os.path.join(self.root_path, "pyfakefs", "tests")
symlinks = [
- ('..', os.path.join(
- real_directory, 'fixtures', 'symlink_dir_relative')),
- ('../all_tests.py', os.path.join(
- real_directory, 'fixtures', 'symlink_file_relative')),
+ (
+ "..",
+ os.path.join(real_directory, "fixtures", "symlink_dir_relative"),
+ ),
+ (
+ "../all_tests.py",
+ os.path.join(real_directory, "fixtures", "symlink_file_relative"),
+ ),
]
with self.create_symlinks(symlinks):
self.filesystem.add_real_directory(
- real_directory, target_path='/path', lazy_read=False)
+ real_directory, target_path="/path", lazy_read=False
+ )
- self.assertTrue(self.filesystem.exists(
- '/path/fixtures/symlink_dir_relative'))
- self.assertTrue(self.filesystem.exists(
- '/path/fixtures/symlink_dir_relative/all_tests.py'))
- self.assertTrue(self.filesystem.exists(
- '/path/fixtures/symlink_file_relative'))
+ self.assertTrue(self.filesystem.exists("/path/fixtures/symlink_dir_relative"))
+ self.assertTrue(
+ self.filesystem.exists("/path/fixtures/symlink_dir_relative/all_tests.py")
+ )
+ self.assertTrue(self.filesystem.exists("/path/fixtures/symlink_file_relative"))
def test_add_existing_real_directory_symlink_lazy_read(self):
self.skip_if_symlink_not_supported(force_real_fs=True)
- real_directory = os.path.join(self.root_path, 'pyfakefs', 'tests')
+ real_directory = os.path.join(self.root_path, "pyfakefs", "tests")
symlinks = [
- ('..', os.path.join(
- real_directory, 'fixtures', 'symlink_dir_relative')),
- ('../all_tests.py', os.path.join(
- real_directory, 'fixtures', 'symlink_file_relative')),
+ (
+ "..",
+ os.path.join(real_directory, "fixtures", "symlink_dir_relative"),
+ ),
+ (
+ "../all_tests.py",
+ os.path.join(real_directory, "fixtures", "symlink_file_relative"),
+ ),
]
with self.create_symlinks(symlinks):
self.filesystem.add_real_directory(
- real_directory, target_path='/path', lazy_read=True)
-
- self.assertTrue(self.filesystem.exists(
- '/path/fixtures/symlink_dir_relative'))
- self.assertTrue(self.filesystem.exists(
- '/path/fixtures/symlink_dir_relative/all_tests.py'))
- self.assertTrue(self.filesystem.exists(
- '/path/fixtures/symlink_file_relative'))
+ real_directory, target_path="/path", lazy_read=True
+ )
+
+ self.assertTrue(
+ self.filesystem.exists("/path/fixtures/symlink_dir_relative")
+ )
+ self.assertTrue(
+ self.filesystem.exists(
+ "/path/fixtures/symlink_dir_relative/all_tests.py"
+ )
+ )
+ self.assertTrue(
+ self.filesystem.exists("/path/fixtures/symlink_file_relative")
+ )
def test_add_existing_real_directory_tree_to_existing_path(self):
- self.filesystem.create_dir('/foo/bar')
+ self.filesystem.create_dir("/foo/bar")
with self.raises_os_error(errno.EEXIST):
- self.filesystem.add_real_directory(
- self.root_path, target_path='/foo/bar')
+ self.filesystem.add_real_directory(self.root_path, target_path="/foo/bar")
def test_add_existing_real_directory_tree_to_other_path(self):
- self.filesystem.add_real_directory(self.root_path,
- target_path='/foo/bar')
+ self.filesystem.add_real_directory(self.root_path, target_path="/foo/bar")
self.assertFalse(
self.filesystem.exists(
- os.path.join(self.pyfakefs_path, 'tests',
- 'fake_filesystem_test.py')))
+ os.path.join(self.pyfakefs_path, "tests", "fake_filesystem_test.py")
+ )
+ )
self.assertTrue(
self.filesystem.exists(
- os.path.join('foo', 'bar', 'pyfakefs', 'tests',
- 'fake_filesystem_test.py')))
+ os.path.join(
+ "foo",
+ "bar",
+ "pyfakefs",
+ "tests",
+ "fake_filesystem_test.py",
+ )
+ )
+ )
self.assertFalse(
self.filesystem.exists(
- os.path.join(self.root_path, 'pyfakefs',
- 'fake_filesystem.py')))
+ os.path.join(self.root_path, "pyfakefs", "fake_filesystem.py")
+ )
+ )
self.assertTrue(
self.filesystem.exists(
- os.path.join('foo', 'bar', 'pyfakefs', '__init__.py')))
+ os.path.join("foo", "bar", "pyfakefs", "__init__.py")
+ )
+ )
def test_get_object_from_lazily_added_real_directory(self):
self.filesystem.is_case_sensitive = True
self.filesystem.add_real_directory(self.root_path)
- self.assertTrue(self.filesystem.get_object(
- os.path.join(self.root_path, 'pyfakefs', 'fake_filesystem.py')))
self.assertTrue(
self.filesystem.get_object(
- os.path.join(self.root_path, 'pyfakefs', '__init__.py')))
+ os.path.join(self.root_path, "pyfakefs", "fake_filesystem.py")
+ )
+ )
+ self.assertTrue(
+ self.filesystem.get_object(
+ os.path.join(self.root_path, "pyfakefs", "__init__.py")
+ )
+ )
def test_add_existing_real_directory_lazily(self):
disk_size = 1024 * 1024 * 1024
- real_dir_path = os.path.join(self.root_path, 'pyfakefs')
+ real_dir_path = os.path.join(self.root_path, "pyfakefs")
self.filesystem.set_disk_usage(disk_size, real_dir_path)
self.filesystem.add_real_directory(real_dir_path)
# the directory contents have not been read, the the disk usage
# has not changed
- self.assertEqual(disk_size,
- self.filesystem.get_disk_usage(real_dir_path).free)
+ self.assertEqual(disk_size, self.filesystem.get_disk_usage(real_dir_path).free)
# checking for existence shall read the directory contents
self.assertTrue(
self.filesystem.get_object(
- os.path.join(real_dir_path, 'fake_filesystem.py')))
+ os.path.join(real_dir_path, "fake_filesystem.py")
+ )
+ )
# so now the free disk space shall have decreased
- self.assertGreater(disk_size,
- self.filesystem.get_disk_usage(real_dir_path).free)
+ self.assertGreater(
+ disk_size, self.filesystem.get_disk_usage(real_dir_path).free
+ )
def test_add_existing_real_directory_not_lazily(self):
disk_size = 1024 * 1024 * 1024
@@ -2260,49 +2439,51 @@ class RealFileSystemAccessTest(RealFsTestCase):
# the directory has been read, so the file sizes have
# been subtracted from the free space
- self.assertGreater(disk_size, self.filesystem.get_disk_usage(
- self.pyfakefs_path).free)
+ self.assertGreater(
+ disk_size, self.filesystem.get_disk_usage(self.pyfakefs_path).free
+ )
def test_add_existing_real_directory_read_write(self):
self.filesystem.add_real_directory(self.pyfakefs_path, read_only=False)
self.assertTrue(self.filesystem.exists(self.pyfakefs_path))
- self.assertTrue(self.filesystem.exists(
- os.path.join(self.pyfakefs_path, 'fake_filesystem.py')))
- self.assertTrue(self.filesystem.exists(
- os.path.join(self.pyfakefs_path, 'fake_pathlib.py')))
+ self.assertTrue(
+ self.filesystem.exists(
+ os.path.join(self.pyfakefs_path, "fake_filesystem.py")
+ )
+ )
+ self.assertTrue(
+ self.filesystem.exists(os.path.join(self.pyfakefs_path, "fake_pathlib.py"))
+ )
- file_path = os.path.join(self.pyfakefs_path, 'pytest_plugin.py')
+ file_path = os.path.join(self.pyfakefs_path, "pytest_plugin.py")
fake_file = self.filesystem.resolve(file_path)
self.check_fake_file_stat(fake_file, file_path)
self.check_writable_file(fake_file, file_path)
def test_add_existing_real_paths_read_only(self):
real_file_path = os.path.realpath(__file__)
- fixture_path = os.path.join(self.pyfakefs_path, 'tests', 'fixtures')
+ fixture_path = os.path.join(self.pyfakefs_path, "tests", "fixtures")
self.filesystem.add_real_paths([real_file_path, fixture_path])
fake_file = self.filesystem.resolve(real_file_path)
self.check_fake_file_stat(fake_file, real_file_path)
self.check_read_only_file(fake_file, real_file_path)
- real_file_path = os.path.join(fixture_path,
- 'module_with_attributes.py')
+ real_file_path = os.path.join(fixture_path, "module_with_attributes.py")
fake_file = self.filesystem.resolve(real_file_path)
self.check_fake_file_stat(fake_file, real_file_path)
self.check_read_only_file(fake_file, real_file_path)
def test_add_existing_real_paths_read_write(self):
real_file_path = os.path.realpath(__file__)
- fixture_path = os.path.join(self.pyfakefs_path, 'tests', 'fixtures')
- self.filesystem.add_real_paths([real_file_path, fixture_path],
- read_only=False)
+ fixture_path = os.path.join(self.pyfakefs_path, "tests", "fixtures")
+ self.filesystem.add_real_paths([real_file_path, fixture_path], read_only=False)
fake_file = self.filesystem.resolve(real_file_path)
self.check_fake_file_stat(fake_file, real_file_path)
self.check_writable_file(fake_file, real_file_path)
- real_file_path = os.path.join(fixture_path,
- 'module_with_attributes.py')
+ real_file_path = os.path.join(fixture_path, "module_with_attributes.py")
fake_file = self.filesystem.resolve(real_file_path)
self.check_fake_file_stat(fake_file, real_file_path)
self.check_writable_file(fake_file, real_file_path)
@@ -2316,28 +2497,28 @@ class FileSideEffectTests(TestCase):
def __side_effect(file_object):
test_case.side_effect_called = True
test_case.side_effect_file_object_content = file_object.contents
+
return __side_effect
def setUp(self):
# use the real path separator to work with the real file system
self.filesystem = fake_filesystem.FakeFilesystem()
- self.filesystem.create_file('/a/b/file_one',
- side_effect=self.side_effect())
+ self.filesystem.create_file("/a/b/file_one", side_effect=self.side_effect())
def test_side_effect_called(self):
fake_open = fake_filesystem.FakeFileOpen(self.filesystem)
self.side_effect_called = False
- with fake_open('/a/b/file_one', 'w') as handle:
- handle.write('foo')
+ with fake_open("/a/b/file_one", "w") as handle:
+ handle.write("foo")
self.assertTrue(self.side_effect_called)
def test_side_effect_file_object(self):
fake_open = fake_filesystem.FakeFileOpen(self.filesystem)
self.side_effect_called = False
- with fake_open('/a/b/file_one', 'w') as handle:
- handle.write('foo')
- self.assertEqual(self.side_effect_file_object_content, 'foo')
+ with fake_open("/a/b/file_one", "w") as handle:
+ handle.write("foo")
+ self.assertEqual(self.side_effect_file_object_content, "foo")
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
diff --git a/pyfakefs/tests/fake_filesystem_unittest_test.py b/pyfakefs/tests/fake_filesystem_unittest_test.py
index f4da663..86f1ae6 100644
--- a/pyfakefs/tests/fake_filesystem_unittest_test.py
+++ b/pyfakefs/tests/fake_filesystem_unittest_test.py
@@ -28,7 +28,6 @@ import sys
import tempfile
import unittest
import warnings
-from distutils.dir_util import copy_tree, remove_tree
from pathlib import Path
from unittest import TestCase, mock
@@ -37,45 +36,52 @@ import pyfakefs.tests.logsio
from pyfakefs import fake_filesystem_unittest, fake_filesystem
from pyfakefs.fake_filesystem import OSType
from pyfakefs.fake_filesystem_unittest import (
- Patcher, Pause, patchfs, PatchMode
+ Patcher,
+ Pause,
+ patchfs,
+ PatchMode,
)
from pyfakefs.tests.fixtures import module_with_attributes
+if sys.version_info < (3, 12):
+ # distutils removed in Python 3.12
+ from distutils.dir_util import copy_tree, remove_tree
+
class TestPatcher(TestCase):
def test_context_manager(self):
with Patcher() as patcher:
- patcher.fs.create_file('/foo/bar', contents='test')
- with open('/foo/bar') as f:
+ patcher.fs.create_file("/foo/bar", contents="test")
+ with open("/foo/bar") as f:
contents = f.read()
- self.assertEqual('test', contents)
+ self.assertEqual("test", contents)
@patchfs
def test_context_decorator(self, fake_fs):
- fake_fs.create_file('/foo/bar', contents='test')
- with open('/foo/bar') as f:
+ fake_fs.create_file("/foo/bar", contents="test")
+ with open("/foo/bar") as f:
contents = f.read()
- self.assertEqual('test', contents)
+ self.assertEqual("test", contents)
class TestPatchfsArgumentOrder(TestCase):
@patchfs
- @mock.patch('os.system')
+ @mock.patch("os.system")
def test_argument_order1(self, fake_fs, patched_system):
- fake_fs.create_file('/foo/bar', contents='test')
- with open('/foo/bar') as f:
+ fake_fs.create_file("/foo/bar", contents="test")
+ with open("/foo/bar") as f:
contents = f.read()
- self.assertEqual('test', contents)
+ self.assertEqual("test", contents)
os.system("foo")
patched_system.assert_called_with("foo")
- @mock.patch('os.system')
+ @mock.patch("os.system")
@patchfs
def test_argument_order2(self, patched_system, fake_fs):
- fake_fs.create_file('/foo/bar', contents='test')
- with open('/foo/bar') as f:
+ fake_fs.create_file("/foo/bar", contents="test")
+ with open("/foo/bar") as f:
contents = f.read()
- self.assertEqual('test', contents)
+ self.assertEqual("test", contents)
os.system("foo")
patched_system.assert_called_with("foo")
@@ -91,136 +97,150 @@ class TestPyfakefsUnittest(TestPyfakefsUnittestBase): # pylint: disable=R0904
def test_open(self):
"""Fake `open()` function is bound"""
- self.assertFalse(os.path.exists('/fake_file.txt'))
- with open('/fake_file.txt', 'w') as f:
+ self.assertFalse(os.path.exists("/fake_file.txt"))
+ with open("/fake_file.txt", "w") as f:
f.write("This test file was created using the open() function.\n")
- self.assertTrue(self.fs.exists('/fake_file.txt'))
- with open('/fake_file.txt') as f:
+ self.assertTrue(self.fs.exists("/fake_file.txt"))
+ with open("/fake_file.txt") as f:
content = f.read()
- self.assertEqual('This test file was created using the '
- 'open() function.\n', content)
+ self.assertEqual(
+ "This test file was created using the " "open() function.\n",
+ content,
+ )
def test_io_open(self):
"""Fake io module is bound"""
- self.assertFalse(os.path.exists('/fake_file.txt'))
- with io.open('/fake_file.txt', 'w') as f:
- f.write("This test file was created using the"
- " io.open() function.\n")
- self.assertTrue(self.fs.exists('/fake_file.txt'))
- with open('/fake_file.txt') as f:
+ self.assertFalse(os.path.exists("/fake_file.txt"))
+ with io.open("/fake_file.txt", "w") as f:
+ f.write("This test file was created using the" " io.open() function.\n")
+ self.assertTrue(self.fs.exists("/fake_file.txt"))
+ with open("/fake_file.txt") as f:
content = f.read()
- self.assertEqual('This test file was created using the '
- 'io.open() function.\n', content)
+ self.assertEqual(
+ "This test file was created using the " "io.open() function.\n",
+ content,
+ )
def test_os(self):
"""Fake os module is bound"""
- self.assertFalse(self.fs.exists('/test/dir1/dir2'))
- os.makedirs('/test/dir1/dir2')
- self.assertTrue(self.fs.exists('/test/dir1/dir2'))
+ self.assertFalse(self.fs.exists("/test/dir1/dir2"))
+ os.makedirs("/test/dir1/dir2")
+ self.assertTrue(self.fs.exists("/test/dir1/dir2"))
def test_glob(self):
"""Fake glob module is bound"""
- is_windows = sys.platform.startswith('win')
- self.assertEqual([], glob.glob('/test/dir1/dir*'))
- self.fs.create_dir('/test/dir1/dir2a')
- matching_paths = glob.glob('/test/dir1/dir*')
+ is_windows = sys.platform.startswith("win")
+ self.assertEqual([], glob.glob("/test/dir1/dir*"))
+ self.fs.create_dir("/test/dir1/dir2a")
+ matching_paths = glob.glob("/test/dir1/dir*")
if is_windows:
- self.assertEqual([r'/test/dir1\dir2a'], matching_paths)
+ self.assertEqual([r"/test/dir1\dir2a"], matching_paths)
else:
- self.assertEqual(['/test/dir1/dir2a'], matching_paths)
- self.fs.create_dir('/test/dir1/dir2b')
- matching_paths = sorted(glob.glob('/test/dir1/dir*'))
+ self.assertEqual(["/test/dir1/dir2a"], matching_paths)
+ self.fs.create_dir("/test/dir1/dir2b")
+ matching_paths = sorted(glob.glob("/test/dir1/dir*"))
if is_windows:
- self.assertEqual([r'/test/dir1\dir2a', r'/test/dir1\dir2b'],
- matching_paths)
+ self.assertEqual([r"/test/dir1\dir2a", r"/test/dir1\dir2b"], matching_paths)
else:
- self.assertEqual(['/test/dir1/dir2a', '/test/dir1/dir2b'],
- matching_paths)
+ self.assertEqual(["/test/dir1/dir2a", "/test/dir1/dir2b"], matching_paths)
def test_shutil(self):
"""Fake shutil module is bound"""
- self.fs.create_dir('/test/dir1/dir2a')
- self.fs.create_dir('/test/dir1/dir2b')
- self.assertTrue(self.fs.exists('/test/dir1/dir2b'))
- self.assertTrue(self.fs.exists('/test/dir1/dir2a'))
+ self.fs.create_dir("/test/dir1/dir2a")
+ self.fs.create_dir("/test/dir1/dir2b")
+ self.assertTrue(self.fs.exists("/test/dir1/dir2b"))
+ self.assertTrue(self.fs.exists("/test/dir1/dir2a"))
- shutil.rmtree('/test/dir1')
- self.assertFalse(self.fs.exists('/test/dir1'))
+ shutil.rmtree("/test/dir1")
+ self.assertFalse(self.fs.exists("/test/dir1"))
def test_fakepathlib(self):
- with pathlib.Path('/fake_file.txt') as p:
- with p.open('w') as f:
- f.write('text')
- is_windows = sys.platform.startswith('win')
+ p = pathlib.Path("/fake_file.txt")
+ with p.open("w") as f:
+ f.write("text")
+ is_windows = sys.platform.startswith("win")
if is_windows:
- self.assertTrue(self.fs.exists(r'\fake_file.txt'))
+ self.assertTrue(self.fs.exists(r"\fake_file.txt"))
else:
- self.assertTrue(self.fs.exists('/fake_file.txt'))
+ self.assertTrue(self.fs.exists("/fake_file.txt"))
class TestPatchingImports(TestPyfakefsUnittestBase):
def test_import_as_other_name(self):
- file_path = '/foo/bar/baz'
+ file_path = "/foo/bar/baz"
self.fs.create_file(file_path)
self.assertTrue(self.fs.exists(file_path))
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists1(file_path))
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists1(file_path))
def test_import_path_from_os(self):
"""Make sure `from os import path` patches `path`."""
- file_path = '/foo/bar/baz'
+ file_path = "/foo/bar/baz"
self.fs.create_file(file_path)
self.assertTrue(self.fs.exists(file_path))
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists2(file_path))
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists2(file_path))
def test_import_path_from_pathlib(self):
- file_path = '/foo/bar'
+ file_path = "/foo/bar"
+ self.fs.create_dir(file_path)
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists3(file_path))
+
+ def test_import_exists_from_os_path(self):
+ file_path = "/foo/bar"
self.fs.create_dir(file_path)
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists3(file_path))
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists5(file_path))
+
+ def test_import_isfile_from_os_path(self):
+ file_path = "/foo/bar"
+ self.fs.create_file(file_path)
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_isfile(file_path))
- def test_import_function_from_os_path(self):
- file_path = '/foo/bar'
+ def test_import_isdir_from_os_path(self):
+ file_path = "/foo/bar"
self.fs.create_dir(file_path)
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists5(file_path))
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_isdir(file_path))
+
+ def test_import_islink_from_os_path(self):
+ file_path = "/foo/bar"
+ link_path = "/foo/link"
+ self.fs.create_file(file_path)
+ self.fs.create_symlink(link_path, file_path)
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_islink(link_path))
def test_import_function_from_os_path_as_other_name(self):
- file_path = '/foo/bar'
+ file_path = "/foo/bar"
self.fs.create_dir(file_path)
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists6(file_path))
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists6(file_path))
def test_import_pathlib_path(self):
- file_path = '/foo/bar'
+ file_path = "/foo/bar"
self.fs.create_dir(file_path)
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists7(file_path))
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists7(file_path))
def test_import_function_from_os(self):
- file_path = '/foo/bar'
- self.fs.create_file(file_path, contents=b'abc')
+ file_path = "/foo/bar"
+ self.fs.create_file(file_path, contents=b"abc")
stat_result = pyfakefs.tests.import_as_example.file_stat1(file_path)
self.assertEqual(3, stat_result.st_size)
def test_import_function_from_os_as_other_name(self):
- file_path = '/foo/bar'
- self.fs.create_file(file_path, contents=b'abc')
+ file_path = "/foo/bar"
+ self.fs.create_file(file_path, contents=b"abc")
stat_result = pyfakefs.tests.import_as_example.file_stat2(file_path)
self.assertEqual(3, stat_result.st_size)
+ @unittest.skipIf(sys.version_info >= (3, 12), "Currently not working in 3.12")
def test_import_open_as_other_name(self):
- file_path = '/foo/bar'
- self.fs.create_file(file_path, contents=b'abc')
+ file_path = "/foo/bar"
+ self.fs.create_file(file_path, contents=b"abc")
contents = pyfakefs.tests.import_as_example.file_contents1(file_path)
- self.assertEqual('abc', contents)
+ self.assertEqual("abc", contents)
+ @unittest.skipIf(sys.version_info >= (3, 12), "Currently not working in 3.12")
def test_import_io_open_as_other_name(self):
- file_path = '/foo/bar'
- self.fs.create_file(file_path, contents=b'abc')
+ file_path = "/foo/bar"
+ self.fs.create_file(file_path, contents=b"abc")
contents = pyfakefs.tests.import_as_example.file_contents2(file_path)
- self.assertEqual('abc', contents)
+ self.assertEqual("abc", contents)
class TestPatchingDefaultArgs(fake_filesystem_unittest.TestCase):
@@ -228,21 +248,19 @@ class TestPatchingDefaultArgs(fake_filesystem_unittest.TestCase):
self.setUpPyfakefs(patch_default_args=True)
def test_path_exists_as_default_arg_in_function(self):
- file_path = '/foo/bar'
+ file_path = "/foo/bar"
self.fs.create_dir(file_path)
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists4(file_path))
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists4(file_path))
def test_path_exists_as_default_arg_in_method(self):
- file_path = '/foo/bar'
+ file_path = "/foo/bar"
self.fs.create_dir(file_path)
sut = pyfakefs.tests.import_as_example.TestDefaultArg()
self.assertTrue(sut.check_if_exists(file_path))
def test_fake_path_exists4(self):
- self.fs.create_file('foo')
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists4('foo'))
+ self.fs.create_file("foo")
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists4("foo"))
class TestAttributesWithFakeModuleNames(TestPyfakefsUnittestBase):
@@ -252,13 +270,11 @@ class TestAttributesWithFakeModuleNames(TestPyfakefsUnittestBase):
def test_attributes(self):
"""Attributes of module under test are not patched"""
- self.assertEqual(module_with_attributes.os, 'os attribute value')
- self.assertEqual(module_with_attributes.path, 'path attribute value')
- self.assertEqual(module_with_attributes.pathlib,
- 'pathlib attribute value')
- self.assertEqual(module_with_attributes.shutil,
- 'shutil attribute value')
- self.assertEqual(module_with_attributes.io, 'io attribute value')
+ self.assertEqual(module_with_attributes.os, "os attribute value")
+ self.assertEqual(module_with_attributes.path, "path attribute value")
+ self.assertEqual(module_with_attributes.pathlib, "pathlib attribute value")
+ self.assertEqual(module_with_attributes.shutil, "shutil attribute value")
+ self.assertEqual(module_with_attributes.io, "io attribute value")
import math as path # noqa: E402 wanted import not at top
@@ -266,8 +282,8 @@ import math as path # noqa: E402 wanted import not at top
class TestPathNotPatchedIfNotOsPath(TestPyfakefsUnittestBase):
"""Tests that `path` is not patched if it is not `os.path`.
- An own path module (in this case an alias to math) can be imported
- and used.
+ An own path module (in this case an alias to math) can be imported
+ and used.
"""
def test_own_path_module(self):
@@ -281,10 +297,11 @@ class FailedPatchingTest(TestPyfakefsUnittestBase):
@unittest.expectedFailure
def test_system_stat(self):
- file_path = '/foo/bar'
- self.fs.create_file(file_path, contents=b'test')
+ file_path = "/foo/bar"
+ self.fs.create_file(file_path, contents=b"test")
self.assertEqual(
- 4, pyfakefs.tests.import_as_example.system_stat(file_path).st_size)
+ 4, pyfakefs.tests.import_as_example.system_stat(file_path).st_size
+ )
class ReloadModuleTest(fake_filesystem_unittest.TestCase):
@@ -294,50 +311,42 @@ class ReloadModuleTest(fake_filesystem_unittest.TestCase):
def setUp(self):
"""Set up the fake file system"""
- self.setUpPyfakefs(
- modules_to_reload=[pyfakefs.tests.import_as_example])
+ self.setUpPyfakefs(modules_to_reload=[pyfakefs.tests.import_as_example])
class NoSkipNamesTest(fake_filesystem_unittest.TestCase):
"""Reference test for additional_skip_names tests:
- make sure that the module is patched by default."""
+ make sure that the module is patched by default."""
def setUp(self):
self.setUpPyfakefs()
def test_path_exists(self):
- self.assertFalse(
- pyfakefs.tests.import_as_example.exists_this_file())
+ self.assertFalse(pyfakefs.tests.import_as_example.exists_this_file())
def test_fake_path_exists1(self):
- self.fs.create_file('foo')
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists1('foo'))
+ self.fs.create_file("foo")
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists1("foo"))
def test_fake_path_exists2(self):
- self.fs.create_file('foo')
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists2('foo'))
+ self.fs.create_file("foo")
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists2("foo"))
def test_fake_path_exists3(self):
- self.fs.create_file('foo')
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists3('foo'))
+ self.fs.create_file("foo")
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists3("foo"))
def test_fake_path_exists5(self):
- self.fs.create_file('foo')
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists5('foo'))
+ self.fs.create_file("foo")
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists5("foo"))
def test_fake_path_exists6(self):
- self.fs.create_file('foo')
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists6('foo'))
+ self.fs.create_file("foo")
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists6("foo"))
def test_fake_path_exists7(self):
- self.fs.create_file('foo')
- self.assertTrue(
- pyfakefs.tests.import_as_example.check_if_exists7('foo'))
+ self.fs.create_file("foo")
+ self.assertTrue(pyfakefs.tests.import_as_example.check_if_exists7("foo"))
def test_open_fails(self):
with self.assertRaises(OSError):
@@ -345,10 +354,10 @@ class NoSkipNamesTest(fake_filesystem_unittest.TestCase):
def test_open_patched_in_module_ending_with_io(self):
# regression test for #569
- file_path = '/foo/bar'
- self.fs.create_file(file_path, contents=b'abc')
+ file_path = "/foo/bar"
+ self.fs.create_file(file_path, contents=b"abc")
contents = pyfakefs.tests.logsio.file_contents(file_path)
- self.assertEqual(b'abc', contents)
+ self.assertEqual(b"abc", contents)
class AdditionalSkipNamesTest(fake_filesystem_unittest.TestCase):
@@ -356,48 +365,43 @@ class AdditionalSkipNamesTest(fake_filesystem_unittest.TestCase):
Passes module name to `additional_skip_names`."""
def setUp(self):
- self.setUpPyfakefs(
- additional_skip_names=['pyfakefs.tests.import_as_example'])
+ self.setUpPyfakefs(additional_skip_names=["pyfakefs.tests.import_as_example"])
def test_path_exists(self):
- self.assertTrue(
- pyfakefs.tests.import_as_example.exists_this_file())
+ self.assertTrue(pyfakefs.tests.import_as_example.exists_this_file())
def test_fake_path_does_not_exist1(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists1('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists1("foo"))
def test_fake_path_does_not_exist2(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists2('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists2("foo"))
def test_fake_path_does_not_exist3(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists3('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists3("foo"))
def test_fake_path_does_not_exist4(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists4('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists4("foo"))
def test_fake_path_does_not_exist5(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists5('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists5("foo"))
def test_fake_path_does_not_exist6(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists6('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists6("foo"))
def test_fake_path_does_not_exist7(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists7('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists7("foo"))
+ @unittest.skipIf(
+ sys.version_info >= (3, 12),
+ "Skip modules currently not working for open in 3.12",
+ )
def test_open_succeeds(self):
pyfakefs.tests.import_as_example.open_this_file()
@@ -410,48 +414,43 @@ class AdditionalSkipNamesModuleTest(fake_filesystem_unittest.TestCase):
Passes module to `additional_skip_names`."""
def setUp(self):
- self.setUpPyfakefs(
- additional_skip_names=[pyfakefs.tests.import_as_example])
+ self.setUpPyfakefs(additional_skip_names=[pyfakefs.tests.import_as_example])
def test_path_exists(self):
- self.assertTrue(
- pyfakefs.tests.import_as_example.exists_this_file())
+ self.assertTrue(pyfakefs.tests.import_as_example.exists_this_file())
def test_fake_path_does_not_exist1(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists1('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists1("foo"))
def test_fake_path_does_not_exist2(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists2('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists2("foo"))
def test_fake_path_does_not_exist3(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists3('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists3("foo"))
def test_fake_path_does_not_exist4(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists4('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists4("foo"))
def test_fake_path_does_not_exist5(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists5('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists5("foo"))
def test_fake_path_does_not_exist6(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists6('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists6("foo"))
def test_fake_path_does_not_exist7(self):
- self.fs.create_file('foo')
- self.assertFalse(
- pyfakefs.tests.import_as_example.check_if_exists7('foo'))
+ self.fs.create_file("foo")
+ self.assertFalse(pyfakefs.tests.import_as_example.check_if_exists7("foo"))
+ @unittest.skipIf(
+ sys.version_info >= (3, 12),
+ "Skip modules currently not working for open in 3.12",
+ )
def test_open_succeeds(self):
pyfakefs.tests.import_as_example.open_this_file()
@@ -462,6 +461,7 @@ class AdditionalSkipNamesModuleTest(fake_filesystem_unittest.TestCase):
class FakeExampleModule:
"""Used to patch a function that uses system-specific functions that
cannot be patched automatically."""
+
_orig_module = pyfakefs.tests.import_as_example
def __init__(self, fs):
@@ -483,14 +483,15 @@ class PatchModuleTest(fake_filesystem_unittest.TestCase):
def setUp(self):
"""Set up the fake file system"""
self.setUpPyfakefs(
- modules_to_patch={
- 'pyfakefs.tests.import_as_example': FakeExampleModule})
+ modules_to_patch={"pyfakefs.tests.import_as_example": FakeExampleModule}
+ )
def test_system_stat(self):
- file_path = '/foo/bar'
- self.fs.create_file(file_path, contents=b'test')
+ file_path = "/foo/bar"
+ self.fs.create_file(file_path, contents=b"test")
self.assertEqual(
- 4, pyfakefs.tests.import_as_example.system_stat(file_path).st_size)
+ 4, pyfakefs.tests.import_as_example.system_stat(file_path).st_size
+ )
class PatchModuleTestUsingDecorator(unittest.TestCase):
@@ -501,18 +502,19 @@ class PatchModuleTestUsingDecorator(unittest.TestCase):
@patchfs
@unittest.expectedFailure
def test_system_stat_failing(self, fake_fs):
- file_path = '/foo/bar'
- fake_fs.create_file(file_path, contents=b'test')
+ file_path = "/foo/bar"
+ fake_fs.create_file(file_path, contents=b"test")
self.assertEqual(
- 4, pyfakefs.tests.import_as_example.system_stat(file_path).st_size)
+ 4, pyfakefs.tests.import_as_example.system_stat(file_path).st_size
+ )
- @patchfs(modules_to_patch={
- 'pyfakefs.tests.import_as_example': FakeExampleModule})
+ @patchfs(modules_to_patch={"pyfakefs.tests.import_as_example": FakeExampleModule})
def test_system_stat(self, fake_fs):
- file_path = '/foo/bar'
- fake_fs.create_file(file_path, contents=b'test')
+ file_path = "/foo/bar"
+ fake_fs.create_file(file_path, contents=b"test")
self.assertEqual(
- 4, pyfakefs.tests.import_as_example.system_stat(file_path).st_size)
+ 4, pyfakefs.tests.import_as_example.system_stat(file_path).st_size
+ )
class NoRootUserTest(fake_filesystem_unittest.TestCase):
@@ -526,17 +528,17 @@ class NoRootUserTest(fake_filesystem_unittest.TestCase):
user rights.
"""
self.fs.is_windows_fs = False
- dir_path = '/foo/bar'
+ dir_path = "/foo/bar"
self.fs.create_dir(dir_path, perm_bits=0o555)
- file_path = dir_path + 'baz'
+ file_path = dir_path + "baz"
with self.assertRaises(OSError):
self.fs.create_file(file_path)
- file_path = '/baz'
+ file_path = "/baz"
self.fs.create_file(file_path)
os.chmod(file_path, 0o400)
with self.assertRaises(OSError):
- open(file_path, 'w')
+ open(file_path, "w")
class PauseResumeTest(fake_filesystem_unittest.TestCase):
@@ -654,13 +656,27 @@ class TestPyfakefsTestCase(unittest.TestCase):
def runTest(self):
pass
- self.test_case = TestTestCase('runTest')
+ self.test_case = TestTestCase("runTest")
def test_test_case_type(self):
self.assertIsInstance(self.test_case, unittest.TestCase)
- self.assertIsInstance(self.test_case,
- fake_filesystem_unittest.TestCaseMixin)
+ self.assertIsInstance(self.test_case, fake_filesystem_unittest.TestCaseMixin)
+
+
+class TestTempDirCreation(fake_filesystem_unittest.TestCase):
+ """Test that the temp directory exists at test start."""
+
+ def setUp(self):
+ self.setUpPyfakefs()
+
+ def test_tempdir_exists(self):
+ self.assertTrue(os.path.exists(tempfile.gettempdir()))
+
+ @unittest.skipIf(sys.platform == "win32", "POSIX only test")
+ def test_tmp_exists(self):
+ # directory or link under Linux, link under macOS
+ self.assertTrue(os.path.exists("/tmp"))
class TestTempFileReload(unittest.TestCase):
@@ -669,19 +685,20 @@ class TestTempFileReload(unittest.TestCase):
def test_fakefs(self):
with Patcher() as patcher:
- patcher.fs.create_file('/mytempfile', contents='abcd')
+ patcher.fs.create_file("/mytempfile", contents="abcd")
def test_value(self):
- v = multiprocessing.Value('I', 0)
+ v = multiprocessing.Value("I", 0)
self.assertEqual(v.value, 0)
-class TestPyfakefsTestCaseMixin(unittest.TestCase,
- fake_filesystem_unittest.TestCaseMixin):
+class TestPyfakefsTestCaseMixin(
+ unittest.TestCase, fake_filesystem_unittest.TestCaseMixin
+):
def test_set_up_pyfakefs(self):
self.setUpPyfakefs()
- self.assertTrue(hasattr(self, 'fs'))
+ self.assertTrue(hasattr(self, "fs"))
self.assertIsInstance(self.fs, fake_filesystem.FakeFilesystem)
@@ -690,41 +707,43 @@ class TestShutilWithZipfile(fake_filesystem_unittest.TestCase):
def setUp(self):
self.setUpPyfakefs()
- self.fs.create_file('foo/bar')
+ self.fs.create_file("foo/bar")
def test_a(self):
- shutil.make_archive('archive', 'zip', root_dir='foo')
+ shutil.make_archive("archive", "zip", root_dir="foo")
def test_b(self):
# used to fail because 'bar' could not be found
- shutil.make_archive('archive', 'zip', root_dir='foo')
+ shutil.make_archive("archive", "zip", root_dir="foo")
-class TestDistutilsCopyTree(fake_filesystem_unittest.TestCase):
- """Regression test for #501."""
+if sys.version_info < (3, 12):
- def setUp(self):
- self.setUpPyfakefs()
- self.fs.create_dir("./test/subdir/")
- self.fs.create_dir("./test/subdir2/")
- self.fs.create_file("./test2/subdir/1.txt")
+ class TestDistutilsCopyTree(fake_filesystem_unittest.TestCase):
+ """Regression test for #501."""
+
+ def setUp(self):
+ self.setUpPyfakefs()
+ self.fs.create_dir("./test/subdir/")
+ self.fs.create_dir("./test/subdir2/")
+ self.fs.create_file("./test2/subdir/1.txt")
- def test_file_copied(self):
- copy_tree("./test2/", "./test/")
- remove_tree("./test2/")
+ def test_file_copied(self):
+ copy_tree("./test2/", "./test/")
+ remove_tree("./test2/")
- self.assertTrue(os.path.isfile('./test/subdir/1.txt'))
- self.assertFalse(os.path.isdir('./test2/'))
+ self.assertTrue(os.path.isfile("./test/subdir/1.txt"))
+ self.assertFalse(os.path.isdir("./test2/"))
- def test_file_copied_again(self):
- # used to fail because 'test2' could not be found
- self.assertTrue(os.path.isfile('./test2/subdir/1.txt'))
+ def test_file_copied_again(self):
+ # used to fail because 'test2' could not be found
+ self.assertTrue(os.path.isfile("./test2/subdir/1.txt"))
- copy_tree("./test2/", "./test/")
- remove_tree("./test2/")
+ copy_tree("./test2/", "./test/")
+ remove_tree("./test2/")
- self.assertTrue(os.path.isfile('./test/subdir/1.txt'))
- self.assertFalse(os.path.isdir('./test2/'))
+ self.assertTrue(os.path.isfile("./test/subdir/1.txt"))
+ self.assertFalse(os.path.isdir("./test2/"))
class PathlibTest(TestCase):
@@ -733,22 +752,27 @@ class PathlibTest(TestCase):
@patchfs
def test_cwd(self, fs):
"""Make sure fake file system is used for os in pathlib"""
- self.assertEqual(os.path.sep, str(pathlib.Path.cwd()))
+ is_windows = sys.platform.startswith("win")
+ root_dir = "C:" + os.path.sep if is_windows else os.path.sep
+ self.assertEqual(root_dir, str(pathlib.Path.cwd()))
dot_abs = pathlib.Path(".").absolute()
- self.assertEqual(os.path.sep, str(dot_abs))
+ self.assertEqual(root_dir, str(dot_abs))
self.assertTrue(dot_abs.exists())
class TestDeprecationSuppression(fake_filesystem_unittest.TestCase):
- @unittest.skipIf(sys.version_info[1] == 6,
- 'Test fails for Python 3.6 for unknown reason')
+ @unittest.skipIf(
+ sys.version_info[1] == 6,
+ "Test fails for Python 3.6 for unknown reason",
+ )
def test_no_deprecation_warning(self):
"""Ensures that deprecation warnings are suppressed during module
lookup, see #542.
"""
- from pyfakefs.tests.fixtures.deprecated_property import \
- DeprecationTest # noqa: F401
+ from pyfakefs.tests.fixtures.deprecated_property import ( # noqa: F401
+ DeprecationTest,
+ )
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("error", DeprecationWarning)
@@ -757,7 +781,7 @@ class TestDeprecationSuppression(fake_filesystem_unittest.TestCase):
def load_configs(configs):
- """ Helper code for patching open_code in auto mode, see issue #554. """
+ """Helper code for patching open_code in auto mode, see issue #554."""
retval = []
for config in configs:
if len(config) > 3 and config[-3:] == ".py":
@@ -768,16 +792,14 @@ def load_configs(configs):
class AutoPatchOpenCodeTestCase(fake_filesystem_unittest.TestCase):
- """ Test patching open_code in auto mode, see issue #554."""
+ """Test patching open_code in auto mode, see issue #554."""
def setUp(self):
self.setUpPyfakefs(patch_open_code=PatchMode.AUTO)
- self.configpy = 'configpy.py'
- self.fs.create_file(
- self.configpy,
- contents="configurable_value='yup'")
- self.config_module = 'pyfakefs.tests.fixtures.config_module'
+ self.configpy = "configpy.py"
+ self.fs.create_file(self.configpy, contents="configurable_value='yup'")
+ self.config_module = "pyfakefs.tests.fixtures.config_module"
def test_both(self):
load_configs([self.configpy, self.config_module])
@@ -793,81 +815,107 @@ class TestOtherFS(fake_filesystem_unittest.TestCase):
def setUp(self):
self.setUpPyfakefs()
+ @mock.patch.dict(os.environ, {"HOME": "/home/john"})
def test_real_file_with_home(self):
"""Regression test for #558"""
- self.fs.is_windows_fs = os.name != 'nt'
+ self.fs.is_windows_fs = os.name != "nt"
+ if self.fs.is_windows_fs:
+ self.fs.is_macos = False
self.fs.add_real_file(__file__)
with open(__file__) as f:
self.assertTrue(f.read())
home = Path.home()
- if sys.version_info < (3, 6):
- # fspath support since Python 3.6
- home = str(home)
os.chdir(home)
with open(__file__) as f:
self.assertTrue(f.read())
def test_windows(self):
self.fs.os = OSType.WINDOWS
- path = r'C:\foo\bar'
- self.assertEqual(path, os.path.join('C:\\', 'foo', 'bar'))
- self.assertEqual(('C:', r'\foo\bar'), os.path.splitdrive(path))
+ path = r"C:\foo\bar"
+ self.assertEqual(path, os.path.join("C:\\", "foo", "bar"))
+ self.assertEqual(("C:", r"\foo\bar"), os.path.splitdrive(path))
self.fs.create_file(path)
self.assertTrue(os.path.exists(path))
self.assertTrue(os.path.exists(path.upper()))
- self.assertTrue(os.path.ismount(r'\\share\foo'))
- self.assertTrue(os.path.ismount(r'C:'))
- self.assertEqual('\\', os.sep)
- self.assertEqual('\\', os.path.sep)
- self.assertEqual('/', os.altsep)
- self.assertEqual(';', os.pathsep)
- self.assertEqual('\r\n', os.linesep)
- self.assertEqual('nul', os.devnull)
+ self.assertTrue(os.path.ismount(r"\\share\foo"))
+ self.assertTrue(os.path.ismount(r"C:"))
+ self.assertEqual("\\", os.sep)
+ self.assertEqual("\\", os.path.sep)
+ self.assertEqual("/", os.altsep)
+ self.assertEqual(";", os.pathsep)
+ self.assertEqual("\r\n", os.linesep)
+ self.assertEqual("nul", os.devnull)
def test_linux(self):
self.fs.os = OSType.LINUX
- path = '/foo/bar'
- self.assertEqual(path, os.path.join('/', 'foo', 'bar'))
- self.assertEqual(('', 'C:/foo/bar'), os.path.splitdrive('C:/foo/bar'))
+ path = "/foo/bar"
+ self.assertEqual(path, os.path.join("/", "foo", "bar"))
+ self.assertEqual(("", "C:/foo/bar"), os.path.splitdrive("C:/foo/bar"))
self.fs.create_file(path)
self.assertTrue(os.path.exists(path))
self.assertFalse(os.path.exists(path.upper()))
- self.assertTrue(os.path.ismount('/'))
- self.assertFalse(os.path.ismount('//share/foo'))
- self.assertEqual('/', os.sep)
- self.assertEqual('/', os.path.sep)
+ self.assertTrue(os.path.ismount("/"))
+ self.assertFalse(os.path.ismount("//share/foo"))
+ self.assertEqual("/", os.sep)
+ self.assertEqual("/", os.path.sep)
self.assertEqual(None, os.altsep)
- self.assertEqual(':', os.pathsep)
- self.assertEqual('\n', os.linesep)
- self.assertEqual('/dev/null', os.devnull)
+ self.assertEqual(":", os.pathsep)
+ self.assertEqual("\n", os.linesep)
+ self.assertEqual("/dev/null", os.devnull)
def test_macos(self):
self.fs.os = OSType.MACOS
- path = '/foo/bar'
- self.assertEqual(path, os.path.join('/', 'foo', 'bar'))
- self.assertEqual(('', 'C:/foo/bar'), os.path.splitdrive('C:/foo/bar'))
+ path = "/foo/bar"
+ self.assertEqual(path, os.path.join("/", "foo", "bar"))
+ self.assertEqual(("", "C:/foo/bar"), os.path.splitdrive("C:/foo/bar"))
self.fs.create_file(path)
self.assertTrue(os.path.exists(path))
self.assertTrue(os.path.exists(path.upper()))
- self.assertTrue(os.path.ismount('/'))
- self.assertFalse(os.path.ismount('//share/foo'))
- self.assertEqual('/', os.sep)
- self.assertEqual('/', os.path.sep)
+ self.assertTrue(os.path.ismount("/"))
+ self.assertFalse(os.path.ismount("//share/foo"))
+ self.assertEqual("/", os.sep)
+ self.assertEqual("/", os.path.sep)
self.assertEqual(None, os.altsep)
- self.assertEqual(':', os.pathsep)
- self.assertEqual('\n', os.linesep)
- self.assertEqual('/dev/null', os.devnull)
+ self.assertEqual(":", os.pathsep)
+ self.assertEqual("\n", os.linesep)
+ self.assertEqual("/dev/null", os.devnull)
def test_drivelike_path(self):
self.fs.os = OSType.LINUX
- folder = Path('/test')
- file_path = folder / 'C:/testfile'
+ folder = Path("/test")
+ file_path = folder / "C:/testfile"
file_path.parent.mkdir(parents=True)
file_path.touch()
- # use str() to be Python 3.5 compatible
- os.chdir(str(folder))
+ os.chdir(folder)
self.assertTrue(os.path.exists(str(file_path.relative_to(folder))))
+@unittest.skipIf(sys.platform != "win32", "Windows-specific behavior")
+class TestAbsolutePathOnWindows(fake_filesystem_unittest.TestCase):
+ @patchfs
+ def test_is_absolute(self, fs):
+ # regression test for #673
+ self.assertTrue(pathlib.Path(".").absolute().is_absolute())
+
+
+@unittest.skipIf(sys.version_info < (3, 8), "Not available before Python 3.8")
+class TestClassSetup(fake_filesystem_unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.setUpClassPyfakefs()
+ cls.fake_fs().create_file("foo/bar", contents="test")
+
+ def test_using_fs_functions(self):
+ self.assertTrue(os.path.exists("foo/bar"))
+ with open("foo/bar") as f:
+ contents = f.read()
+ self.assertEqual("test", contents)
+
+ def test_using_fakefs(self):
+ self.assertTrue(self.fs.exists("foo/bar"))
+ f = self.fs.get_object("foo/bar")
+ self.assertEqual("test", f.contents)
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/pyfakefs/tests/fake_filesystem_vs_real_test.py b/pyfakefs/tests/fake_filesystem_vs_real_test.py
index 3be1076..3cc8f6c 100644
--- a/pyfakefs/tests/fake_filesystem_vs_real_test.py
+++ b/pyfakefs/tests/fake_filesystem_vs_real_test.py
@@ -22,14 +22,14 @@ import tempfile
import time
import unittest
-from pyfakefs import fake_filesystem
+from pyfakefs import fake_filesystem, fake_os, fake_open
from pyfakefs.helpers import IS_PYPY
def sep(path):
- """Converts slashes in the path to the architecture's path seperator."""
+ """Converts slashes in the path to the architecture's path separator."""
if isinstance(path, str):
- return path.replace('/', os.sep)
+ return path.replace("/", os.sep)
return path
@@ -42,8 +42,8 @@ def _get_errno(raised_error):
class TestCase(unittest.TestCase):
- is_windows = sys.platform.startswith('win')
- _FAKE_FS_BASE = sep('/fakefs')
+ is_windows = sys.platform.startswith("win")
+ _FAKE_FS_BASE = "C:\\fakefs" if is_windows else "/fakefs"
class FakeFilesystemVsRealTest(TestCase):
@@ -51,43 +51,45 @@ class FakeFilesystemVsRealTest(TestCase):
"""For a given path, return paths in the real and fake filesystems."""
if not path:
return None, None
- return (os.path.join(self.real_base, path),
- os.path.join(self.fake_base, path))
+ return (
+ os.path.join(self.real_base, path),
+ os.path.join(self.fake_base, path),
+ )
def _create_test_file(self, file_type, path, contents=None):
"""Create a dir, file, or link in both the real fs and the fake."""
path = sep(path)
self._created_files.append([file_type, path, contents])
real_path, fake_path = self._paths(path)
- if file_type == 'd':
+ if file_type == "d":
os.mkdir(real_path)
self.fake_os.mkdir(fake_path)
- if file_type == 'f':
- fh = open(real_path, 'w')
- fh.write(contents or '')
+ if file_type == "f":
+ fh = open(real_path, "w")
+ fh.write(contents or "")
fh.close()
- fh = self.fake_open(fake_path, 'w')
- fh.write(contents or '')
+ fh = self.fake_open(fake_path, "w")
+ fh.write(contents or "")
fh.close()
# b for binary file
- if file_type == 'b':
- fh = open(real_path, 'wb')
- fh.write(contents or '')
+ if file_type == "b":
+ fh = open(real_path, "wb")
+ fh.write(contents or "")
fh.close()
- fh = self.fake_open(fake_path, 'wb')
- fh.write(contents or '')
+ fh = self.fake_open(fake_path, "wb")
+ fh.write(contents or "")
fh.close()
# l for symlink, h for hard link
- if file_type in ('l', 'h'):
+ if file_type in ("l", "h"):
real_target, fake_target = (contents, contents)
# If it begins with '/', make it relative to the base. You can't go
# creating files in / for the real file system.
if contents.startswith(os.sep):
real_target, fake_target = self._paths(contents[1:])
- if file_type == 'l':
+ if file_type == "l":
os.symlink(real_target, real_path)
self.fake_os.symlink(fake_target, fake_path)
- elif file_type == 'h':
+ elif file_type == "h":
os.link(real_target, real_path)
self.fake_os.link(fake_target, fake_path)
@@ -95,11 +97,10 @@ class FakeFilesystemVsRealTest(TestCase):
# Base paths in the real and test file systems. We keep them different
# so that missing features in the fake don't fall through to the base
# operations and magically succeed.
- tsname = 'fakefs.%s' % time.time()
+ tsname = "fakefs.%s" % time.time()
self.cwd = os.getcwd()
# Fully expand the base_path - required on OS X.
- self.real_base = os.path.realpath(
- os.path.join(tempfile.gettempdir(), tsname))
+ self.real_base = os.path.realpath(os.path.join(tempfile.gettempdir(), tsname))
os.chdir(tempfile.gettempdir())
if os.path.isdir(self.real_base):
shutil.rmtree(self.real_base)
@@ -111,8 +112,8 @@ class FakeFilesystemVsRealTest(TestCase):
self.fake_filesystem = fake_filesystem.FakeFilesystem()
self.fake_filesystem.create_dir(self.fake_base)
- self.fake_os = fake_filesystem.FakeOsModule(self.fake_filesystem)
- self.fake_open = fake_filesystem.FakeFileOpen(self.fake_filesystem)
+ self.fake_os = fake_os.FakeOsModule(self.fake_filesystem)
+ self.fake_open = fake_open.FakeFileOpen(self.fake_filesystem)
self._created_files = []
os.chdir(self.real_base)
@@ -127,25 +128,28 @@ class FakeFilesystemVsRealTest(TestCase):
rev_files.reverse()
for info in rev_files:
real_path, fake_path = self._paths(info[1])
- if info[0] == 'd':
+ if info[0] == "d":
try:
os.rmdir(real_path)
except OSError as e:
- if 'Directory not empty' in e:
- self.fail('Real path %s not empty: %s : %s' % (
- real_path, e, os.listdir(real_path)))
+ if "Directory not empty" in e:
+ self.fail(
+ "Real path %s not empty: %s : %s"
+ % (real_path, e, os.listdir(real_path))
+ )
else:
raise
self.fake_os.rmdir(fake_path)
- if info[0] == 'f' or info[0] == 'l':
+ if info[0] == "f" or info[0] == "l":
os.remove(real_path)
self.fake_os.remove(fake_path)
finally:
shutil.rmtree(self.real_base)
os.chdir(self.cwd)
- def _compare_behaviors(self, method_name, path, real, fake,
- method_returns_path=False):
+ def _compare_behaviors(
+ self, method_name, path, real, fake, method_returns_path=False
+ ):
"""Invoke an os method in both real and fake contexts and compare
results.
@@ -174,44 +178,63 @@ class FakeFilesystemVsRealTest(TestCase):
def _error_class(exc):
if exc:
- if hasattr(exc, 'errno'):
- return '{}({})'.format(exc.__class__.__name__, exc.errno)
+ if hasattr(exc, "errno"):
+ return "{}({})".format(exc.__class__.__name__, exc.errno)
return exc.__class__.__name__
- return 'None'
+ return "None"
real_err, real_value = self._get_real_value(method_name, path, real)
fake_err, fake_value = self._get_fake_value(method_name, path, fake)
- method_call = f'{method_name}'
- method_call += '()' if path == () else '({path})'
- # We only compare on the error class because the acutal error contents
+ method_call = f"{method_name}"
+ method_call += "()" if path == () else "({path})"
+ # We only compare on the error class because the actual error contents
# is almost always different because of the file paths.
if _error_class(real_err) != _error_class(fake_err):
if real_err is None:
- return '%s: real version returned %s, fake raised %s' % (
- method_call, real_value, _error_class(fake_err))
+ return "%s: real version returned %s, fake raised %s" % (
+ method_call,
+ real_value,
+ _error_class(fake_err),
+ )
if fake_err is None:
- return '%s: real version raised %s, fake returned %s' % (
- method_call, _error_class(real_err), fake_value)
- return '%s: real version raised %s, fake raised %s' % (
- method_call, _error_class(real_err), _error_class(fake_err))
+ return "%s: real version raised %s, fake returned %s" % (
+ method_call,
+ _error_class(real_err),
+ fake_value,
+ )
+ return "%s: real version raised %s, fake raised %s" % (
+ method_call,
+ _error_class(real_err),
+ _error_class(fake_err),
+ )
real_errno = _get_errno(real_err)
fake_errno = _get_errno(fake_err)
if real_errno != fake_errno:
- return '%s(%s): both raised %s, real errno %s, fake errno %s' % (
- method_name, path, _error_class(real_err),
- real_errno, fake_errno)
+ return "%s(%s): both raised %s, real errno %s, fake errno %s" % (
+ method_name,
+ path,
+ _error_class(real_err),
+ real_errno,
+ fake_errno,
+ )
# If the method is supposed to return a full path AND both values
# begin with the expected full path, then trim it off.
if method_returns_path:
- if (real_value and fake_value
- and real_value.startswith(self.real_base)
- and fake_value.startswith(self.fake_base)):
- real_value = real_value[len(self.real_base):]
- fake_value = fake_value[len(self.fake_base):]
+ if (
+ real_value
+ and fake_value
+ and real_value.startswith(self.real_base)
+ and fake_value.startswith(self.fake_base)
+ ):
+ real_value = real_value[len(self.real_base) :]
+ fake_value = fake_value[len(self.fake_base) :]
if real_value != fake_value:
- return '%s: real return %s, fake returned %s' % (
- method_call, real_value, fake_value)
+ return "%s: real return %s, fake returned %s" % (
+ method_call,
+ real_value,
+ fake_value,
+ )
return None
@staticmethod
@@ -251,8 +274,9 @@ class FakeFilesystemVsRealTest(TestCase):
real_err = e
return real_err, real_value
- def assertOsMethodBehaviorMatches(self, method_name, path,
- method_returns_path=False):
+ def assertOsMethodBehaviorMatches(
+ self, method_name, path, method_returns_path=False
+ ):
"""Invoke an os method in both real and fake contexts and compare.
For a given method name (from the os module) and a path, compare the
@@ -270,11 +294,13 @@ class FakeFilesystemVsRealTest(TestCase):
A description of the difference in behavior, or None.
"""
path = sep(path)
- return self._compare_behaviors(method_name, path, os, self.fake_os,
- method_returns_path)
+ return self._compare_behaviors(
+ method_name, path, os, self.fake_os, method_returns_path
+ )
- def diff_open_method_behavior(self, method_name, path, mode, data,
- method_returns_data=True):
+ def diff_open_method_behavior(
+ self, method_name, path, mode, data, method_returns_data=True
+ ):
"""Invoke an open method in both real and fkae contexts and compare.
Args:
@@ -295,10 +321,12 @@ class FakeFilesystemVsRealTest(TestCase):
with open(path, mode) as real_fh:
with self.fake_open(path, mode) as fake_fh:
return self._compare_behaviors(
- method_name, data, real_fh, fake_fh, method_returns_data)
+ method_name, data, real_fh, fake_fh, method_returns_data
+ )
- def diff_os_path_method_behavior(self, method_name, path,
- method_returns_path=False):
+ def diff_os_path_method_behavior(
+ self, method_name, path, method_returns_path=False
+ ):
"""Invoke an os.path method in both real and fake contexts and compare.
For a given method name (from the os.path module) and a path, compare
@@ -315,12 +343,13 @@ class FakeFilesystemVsRealTest(TestCase):
Returns:
A description of the difference in behavior, or None.
"""
- return self._compare_behaviors(method_name, path, os.path,
- self.fake_os.path,
- method_returns_path)
+ return self._compare_behaviors(
+ method_name, path, os.path, self.fake_os.path, method_returns_path
+ )
- def assertOsPathMethodBehaviorMatches(self, method_name, path,
- method_returns_path=False):
+ def assertOsPathMethodBehaviorMatches(
+ self, method_name, path, method_returns_path=False
+ ):
"""Assert that an os.path behaves the same in both real and
fake contexts.
@@ -337,25 +366,24 @@ class FakeFilesystemVsRealTest(TestCase):
AssertionError if there is any difference in behavior.
"""
path = sep(path)
- diff = self.diff_os_path_method_behavior(
- method_name, path, method_returns_path)
+ diff = self.diff_os_path_method_behavior(method_name, path, method_returns_path)
if diff:
self.fail(diff)
def assertAllOsBehaviorsMatch(self, path):
path = sep(path)
- os_method_names = [] if self.is_windows else ['readlink']
- os_method_names_no_args = ['getcwd']
- os_path_method_names = ['isabs', 'isdir']
+ os_method_names = [] if self.is_windows else ["readlink"]
+ os_method_names_no_args = ["getcwd"]
+ os_path_method_names = ["isabs", "isdir"]
if not self.is_windows:
- os_path_method_names += ['islink', 'lexists']
+ os_path_method_names += ["islink", "lexists"]
if not self.is_windows or not IS_PYPY:
- os_path_method_names += ['isfile', 'exists']
+ os_path_method_names += ["isfile", "exists"]
wrapped_methods = [
- ['access', self._access_real, self._access_fake],
- ['stat.size', self._stat_size_real, self._stat_size_fake],
- ['lstat.size', self._lstat_size_real, self._lstat_size_fake]
+ ["access", self._access_real, self._access_fake],
+ ["stat.size", self._stat_size_real, self._stat_size_fake],
+ ["lstat.size", self._lstat_size_real, self._lstat_size_fake],
]
differences = []
@@ -364,8 +392,9 @@ class FakeFilesystemVsRealTest(TestCase):
if diff:
differences.append(diff)
for method_name in os_method_names_no_args:
- diff = self.assertOsMethodBehaviorMatches(method_name, (),
- method_returns_path=True)
+ diff = self.assertOsMethodBehaviorMatches(
+ method_name, (), method_returns_path=True
+ )
if diff:
differences.append(diff)
for method_name in os_path_method_names:
@@ -377,18 +406,19 @@ class FakeFilesystemVsRealTest(TestCase):
if diff:
differences.append(diff)
if differences:
- self.fail('Behaviors do not match for %s:\n %s' %
- (path, '\n '.join(differences)))
+ self.fail(
+ "Behaviors do not match for %s:\n %s"
+ % (path, "\n ".join(differences))
+ )
def assertFileHandleBehaviorsMatch(self, path, mode, data):
path = sep(path)
- write_method_names = ['write', 'writelines']
- read_method_names = ['read', 'readlines']
- other_method_names = ['truncate', 'flush', 'close']
+ write_method_names = ["write", "writelines"]
+ read_method_names = ["read", "readlines"]
+ other_method_names = ["truncate", "flush", "close"]
differences = []
for method_name in write_method_names:
- diff = self.diff_open_method_behavior(
- method_name, path, mode, data)
+ diff = self.diff_open_method_behavior(method_name, path, mode, data)
if diff:
differences.append(diff)
for method_name in read_method_names + other_method_names:
@@ -396,8 +426,10 @@ class FakeFilesystemVsRealTest(TestCase):
if diff:
differences.append(diff)
if differences:
- self.fail('Behaviors do not match for %s:\n %s' %
- (path, '\n '.join(differences)))
+ self.fail(
+ "Behaviors do not match for %s:\n %s"
+ % (path, "\n ".join(differences))
+ )
def assertFileHandleOpenBehaviorsMatch(self, *args, **kwargs):
"""Compare open() function invocation between real and fake.
@@ -429,18 +461,20 @@ class FakeFilesystemVsRealTest(TestCase):
fake_err = e
# default equal in case one is None and other is not.
- is_exception_equal = (real_err == fake_err)
+ is_exception_equal = real_err == fake_err
if real_err and fake_err:
# exception __eq__ doesn't evaluate equal ever, thus manual check.
- is_exception_equal = (type(real_err) is type(fake_err) and
- real_err.args == fake_err.args)
+ is_exception_equal = (
+ type(real_err) is type(fake_err) and real_err.args == fake_err.args
+ )
if not is_exception_equal:
- msg = (
- "Behaviors don't match on open with args %s & kwargs %s.\n" %
- (args, kwargs))
- real_err_msg = 'Real open results in: %s\n' % repr(real_err)
- fake_err_msg = 'Fake open results in: %s\n' % repr(fake_err)
+ msg = "Behaviors don't match on open with args %s & kwargs %s.\n" % (
+ args,
+ kwargs,
+ )
+ real_err_msg = "Real open results in: %s\n" % repr(real_err)
+ fake_err_msg = "Fake open results in: %s\n" % repr(fake_err)
self.fail(msg + real_err_msg + fake_err_msg)
# Helpers for checks which are not straight method calls.
@@ -490,211 +524,204 @@ class FakeFilesystemVsRealTest(TestCase):
def test_isabs(self):
# We do not have to create any files for isabs.
- self.assertOsPathMethodBehaviorMatches('isabs', None)
- self.assertOsPathMethodBehaviorMatches('isabs', '')
- self.assertOsPathMethodBehaviorMatches('isabs', '/')
- self.assertOsPathMethodBehaviorMatches('isabs', '/a')
- self.assertOsPathMethodBehaviorMatches('isabs', 'a')
+ self.assertOsPathMethodBehaviorMatches("isabs", None)
+ self.assertOsPathMethodBehaviorMatches("isabs", "")
+ self.assertOsPathMethodBehaviorMatches("isabs", "/")
+ self.assertOsPathMethodBehaviorMatches("isabs", "/a")
+ self.assertOsPathMethodBehaviorMatches("isabs", "a")
def test_none_path(self):
self.assertAllOsBehaviorsMatch(None)
def test_empty_path(self):
- self.assertAllOsBehaviorsMatch('')
+ self.assertAllOsBehaviorsMatch("")
def test_root_path(self):
- self.assertAllOsBehaviorsMatch('/')
+ self.assertAllOsBehaviorsMatch("/")
def test_non_existant_file(self):
- self.assertAllOsBehaviorsMatch('foo')
+ self.assertAllOsBehaviorsMatch("foo")
def test_empty_file(self):
- self._create_test_file('f', 'aFile')
- self.assertAllOsBehaviorsMatch('aFile')
+ self._create_test_file("f", "aFile")
+ self.assertAllOsBehaviorsMatch("aFile")
def test_file_with_contents(self):
- self._create_test_file('f', 'aFile', 'some contents')
- self.assertAllOsBehaviorsMatch('aFile')
+ self._create_test_file("f", "aFile", "some contents")
+ self.assertAllOsBehaviorsMatch("aFile")
def test_file_with_binary_contents(self):
- self._create_test_file('b', 'aFile', b'some contents')
- self.assertAllOsBehaviorsMatch('aFile')
+ self._create_test_file("b", "aFile", b"some contents")
+ self.assertAllOsBehaviorsMatch("aFile")
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_sym_link_to_empty_file(self):
- self._create_test_file('f', 'aFile')
- self._create_test_file('l', 'link_to_empty', 'aFile')
- self.assertAllOsBehaviorsMatch('link_to_empty')
+ self._create_test_file("f", "aFile")
+ self._create_test_file("l", "link_to_empty", "aFile")
+ self.assertAllOsBehaviorsMatch("link_to_empty")
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_hard_link_to_empty_file(self):
- self._create_test_file('f', 'aFile')
- self._create_test_file('h', 'link_to_empty', 'aFile')
- self.assertAllOsBehaviorsMatch('link_to_empty')
+ self._create_test_file("f", "aFile")
+ self._create_test_file("h", "link_to_empty", "aFile")
+ self.assertAllOsBehaviorsMatch("link_to_empty")
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_sym_link_to_real_file(self):
- self._create_test_file('f', 'aFile', 'some contents')
- self._create_test_file('l', 'link_to_file', 'aFile')
- self.assertAllOsBehaviorsMatch('link_to_file')
+ self._create_test_file("f", "aFile", "some contents")
+ self._create_test_file("l", "link_to_file", "aFile")
+ self.assertAllOsBehaviorsMatch("link_to_file")
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_hard_link_to_real_file(self):
- self._create_test_file('f', 'aFile', 'some contents')
- self._create_test_file('h', 'link_to_file', 'aFile')
- self.assertAllOsBehaviorsMatch('link_to_file')
+ self._create_test_file("f", "aFile", "some contents")
+ self._create_test_file("h", "link_to_file", "aFile")
+ self.assertAllOsBehaviorsMatch("link_to_file")
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_broken_sym_link(self):
- self._create_test_file('l', 'broken_link', 'broken')
- self._create_test_file('l', 'loop', '/a/loop')
- self.assertAllOsBehaviorsMatch('broken_link')
+ self._create_test_file("l", "broken_link", "broken")
+ self._create_test_file("l", "loop", "/a/loop")
+ self.assertAllOsBehaviorsMatch("broken_link")
def test_file_in_a_folder(self):
- self._create_test_file('d', 'a')
- self._create_test_file('d', 'a/b')
- self._create_test_file('f', 'a/b/file', 'contents')
- self.assertAllOsBehaviorsMatch('a/b/file')
+ self._create_test_file("d", "a")
+ self._create_test_file("d", "a/b")
+ self._create_test_file("f", "a/b/file", "contents")
+ self.assertAllOsBehaviorsMatch("a/b/file")
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_absolute_sym_link_to_folder(self):
- self._create_test_file('d', 'a')
- self._create_test_file('d', 'a/b')
- self._create_test_file('f', 'a/b/file', 'contents')
- self._create_test_file('l', 'a/link', '/a/b')
- self.assertAllOsBehaviorsMatch('a/link/file')
+ self._create_test_file("d", "a")
+ self._create_test_file("d", "a/b")
+ self._create_test_file("f", "a/b/file", "contents")
+ self._create_test_file("l", "a/link", "/a/b")
+ self.assertAllOsBehaviorsMatch("a/link/file")
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_link_to_folder_after_chdir(self):
- self._create_test_file('d', 'a')
- self._create_test_file('d', 'a/b')
- self._create_test_file('f', 'a/b/file', 'contents')
- self._create_test_file('l', 'a/link', '/a/b')
+ self._create_test_file("d", "a")
+ self._create_test_file("d", "a/b")
+ self._create_test_file("f", "a/b/file", "contents")
+ self._create_test_file("l", "a/link", "/a/b")
- real_dir, fake_dir = self._paths('a/b')
+ real_dir, fake_dir = self._paths("a/b")
os.chdir(real_dir)
self.fake_os.chdir(fake_dir)
- self.assertAllOsBehaviorsMatch('file')
+ self.assertAllOsBehaviorsMatch("file")
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_relative_sym_link_to_folder(self):
- self._create_test_file('d', 'a')
- self._create_test_file('d', 'a/b')
- self._create_test_file('f', 'a/b/file', 'contents')
- self._create_test_file('l', 'a/link', 'b')
- self.assertAllOsBehaviorsMatch('a/link/file')
+ self._create_test_file("d", "a")
+ self._create_test_file("d", "a/b")
+ self._create_test_file("f", "a/b/file", "contents")
+ self._create_test_file("l", "a/link", "b")
+ self.assertAllOsBehaviorsMatch("a/link/file")
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_sym_link_to_parent(self):
# Soft links on HFS+ / OS X behave differently.
- if os.uname()[0] != 'Darwin':
- self._create_test_file('d', 'a')
- self._create_test_file('d', 'a/b')
- self._create_test_file('l', 'a/b/c', '..')
- self.assertAllOsBehaviorsMatch('a/b/c')
+ if os.uname()[0] != "Darwin":
+ self._create_test_file("d", "a")
+ self._create_test_file("d", "a/b")
+ self._create_test_file("l", "a/b/c", "..")
+ self.assertAllOsBehaviorsMatch("a/b/c")
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_path_through_sym_link_to_parent(self):
- self._create_test_file('d', 'a')
- self._create_test_file('f', 'a/target', 'contents')
- self._create_test_file('d', 'a/b')
- self._create_test_file('l', 'a/b/c', '..')
- self.assertAllOsBehaviorsMatch('a/b/c/target')
+ self._create_test_file("d", "a")
+ self._create_test_file("f", "a/target", "contents")
+ self._create_test_file("d", "a/b")
+ self._create_test_file("l", "a/b/c", "..")
+ self.assertAllOsBehaviorsMatch("a/b/c/target")
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_sym_link_to_sibling_directory(self):
- self._create_test_file('d', 'a')
- self._create_test_file('d', 'a/b')
- self._create_test_file('d', 'a/sibling_of_b')
- self._create_test_file('f', 'a/sibling_of_b/target', 'contents')
- self._create_test_file('l', 'a/b/c', '../sibling_of_b')
- self.assertAllOsBehaviorsMatch('a/b/c/target')
-
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ self._create_test_file("d", "a")
+ self._create_test_file("d", "a/b")
+ self._create_test_file("d", "a/sibling_of_b")
+ self._create_test_file("f", "a/sibling_of_b/target", "contents")
+ self._create_test_file("l", "a/b/c", "../sibling_of_b")
+ self.assertAllOsBehaviorsMatch("a/b/c/target")
+
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_sym_link_to_sibling_directory_non_existant_file(self):
- self._create_test_file('d', 'a')
- self._create_test_file('d', 'a/b')
- self._create_test_file('d', 'a/sibling_of_b')
- self._create_test_file('f', 'a/sibling_of_b/target', 'contents')
- self._create_test_file('l', 'a/b/c', '../sibling_of_b')
- self.assertAllOsBehaviorsMatch('a/b/c/file_does_not_exist')
-
- @unittest.skipIf(TestCase.is_windows, 'no symlink in Windows')
+ self._create_test_file("d", "a")
+ self._create_test_file("d", "a/b")
+ self._create_test_file("d", "a/sibling_of_b")
+ self._create_test_file("f", "a/sibling_of_b/target", "contents")
+ self._create_test_file("l", "a/b/c", "../sibling_of_b")
+ self.assertAllOsBehaviorsMatch("a/b/c/file_does_not_exist")
+
+ @unittest.skipIf(TestCase.is_windows, "no symlink in Windows")
def test_broken_sym_link_to_sibling_directory(self):
- self._create_test_file('d', 'a')
- self._create_test_file('d', 'a/b')
- self._create_test_file('d', 'a/sibling_of_b')
- self._create_test_file('f', 'a/sibling_of_b/target', 'contents')
- self._create_test_file('l', 'a/b/c', '../broken_sibling_of_b')
- self.assertAllOsBehaviorsMatch('a/b/c/target')
+ self._create_test_file("d", "a")
+ self._create_test_file("d", "a/b")
+ self._create_test_file("d", "a/sibling_of_b")
+ self._create_test_file("f", "a/sibling_of_b/target", "contents")
+ self._create_test_file("l", "a/b/c", "../broken_sibling_of_b")
+ self.assertAllOsBehaviorsMatch("a/b/c/target")
def test_relative_path(self):
- self._create_test_file('d', 'a')
- self._create_test_file('d', 'a/b')
- self._create_test_file('d', 'a/sibling_of_b')
- self._create_test_file('f', 'a/sibling_of_b/target', 'contents')
- self.assertAllOsBehaviorsMatch('a/b/../sibling_of_b/target')
+ self._create_test_file("d", "a")
+ self._create_test_file("d", "a/b")
+ self._create_test_file("d", "a/sibling_of_b")
+ self._create_test_file("f", "a/sibling_of_b/target", "contents")
+ self.assertAllOsBehaviorsMatch("a/b/../sibling_of_b/target")
def test_broken_relative_path(self):
- self._create_test_file('d', 'a')
- self._create_test_file('d', 'a/b')
- self._create_test_file('d', 'a/sibling_of_b')
- self._create_test_file('f', 'a/sibling_of_b/target', 'contents')
- self.assertAllOsBehaviorsMatch('a/b/../broken/target')
+ self._create_test_file("d", "a")
+ self._create_test_file("d", "a/b")
+ self._create_test_file("d", "a/sibling_of_b")
+ self._create_test_file("f", "a/sibling_of_b/target", "contents")
+ self.assertAllOsBehaviorsMatch("a/b/../broken/target")
def test_bad_relative_path(self):
- self._create_test_file('d', 'a')
- self._create_test_file('f', 'a/target', 'contents')
- self._create_test_file('d', 'a/b')
- self._create_test_file('d', 'a/sibling_of_b')
- self._create_test_file('f', 'a/sibling_of_b/target', 'contents')
- self.assertAllOsBehaviorsMatch('a/b/../broken/../target')
+ self._create_test_file("d", "a")
+ self._create_test_file("f", "a/target", "contents")
+ self._create_test_file("d", "a/b")
+ self._create_test_file("d", "a/sibling_of_b")
+ self._create_test_file("f", "a/sibling_of_b/target", "contents")
+ self.assertAllOsBehaviorsMatch("a/b/../broken/../target")
def test_getmtime_nonexistant_path(self):
- self.assertOsPathMethodBehaviorMatches('getmtime', 'no/such/path')
+ self.assertOsPathMethodBehaviorMatches("getmtime", "no/such/path")
def test_builtin_open_modes(self):
- self._create_test_file('f', 'read', 'some contents')
- self._create_test_file('f', 'write', 'some contents')
- self._create_test_file('f', 'append', 'some contents')
- self.assertFileHandleBehaviorsMatch('read', 'r', 'other contents')
- self.assertFileHandleBehaviorsMatch('write', 'w', 'other contents')
- self.assertFileHandleBehaviorsMatch('append', 'a', 'other contents')
- self._create_test_file('f', 'readplus', 'some contents')
- self._create_test_file('f', 'writeplus', 'some contents')
- self.assertFileHandleBehaviorsMatch(
- 'readplus', 'r+', 'other contents')
- self.assertFileHandleBehaviorsMatch(
- 'writeplus', 'w+', 'other contents')
- self._create_test_file('b', 'binaryread', b'some contents')
- self._create_test_file('b', 'binarywrite', b'some contents')
- self._create_test_file('b', 'binaryappend', b'some contents')
- self.assertFileHandleBehaviorsMatch(
- 'binaryread', 'rb', b'other contents')
- self.assertFileHandleBehaviorsMatch(
- 'binarywrite', 'wb', b'other contents')
- self.assertFileHandleBehaviorsMatch(
- 'binaryappend', 'ab', b'other contents')
- self.assertFileHandleBehaviorsMatch('read', 'rb', 'other contents')
- self.assertFileHandleBehaviorsMatch('write', 'wb', 'other contents')
- self.assertFileHandleBehaviorsMatch('append', 'ab', 'other contents')
+ self._create_test_file("f", "read", "some contents")
+ self._create_test_file("f", "write", "some contents")
+ self._create_test_file("f", "append", "some contents")
+ self.assertFileHandleBehaviorsMatch("read", "r", "other contents")
+ self.assertFileHandleBehaviorsMatch("write", "w", "other contents")
+ self.assertFileHandleBehaviorsMatch("append", "a", "other contents")
+ self._create_test_file("f", "readplus", "some contents")
+ self._create_test_file("f", "writeplus", "some contents")
+ self.assertFileHandleBehaviorsMatch("readplus", "r+", "other contents")
+ self.assertFileHandleBehaviorsMatch("writeplus", "w+", "other contents")
+ self._create_test_file("b", "binaryread", b"some contents")
+ self._create_test_file("b", "binarywrite", b"some contents")
+ self._create_test_file("b", "binaryappend", b"some contents")
+ self.assertFileHandleBehaviorsMatch("binaryread", "rb", b"other contents")
+ self.assertFileHandleBehaviorsMatch("binarywrite", "wb", b"other contents")
+ self.assertFileHandleBehaviorsMatch("binaryappend", "ab", b"other contents")
+ self.assertFileHandleBehaviorsMatch("read", "rb", "other contents")
+ self.assertFileHandleBehaviorsMatch("write", "wb", "other contents")
+ self.assertFileHandleBehaviorsMatch("append", "ab", "other contents")
# binary cannot have encoding
- self.assertFileHandleOpenBehaviorsMatch('read', 'rb', encoding='enc')
- self.assertFileHandleOpenBehaviorsMatch(
- 'write', mode='wb', encoding='enc')
- self.assertFileHandleOpenBehaviorsMatch('append', 'ab', encoding='enc')
+ self.assertFileHandleOpenBehaviorsMatch("read", "rb", encoding="enc")
+ self.assertFileHandleOpenBehaviorsMatch("write", mode="wb", encoding="enc")
+ self.assertFileHandleOpenBehaviorsMatch("append", "ab", encoding="enc")
# text can have encoding
- self.assertFileHandleOpenBehaviorsMatch('read', 'r', encoding='utf-8')
- self.assertFileHandleOpenBehaviorsMatch('write', 'w', encoding='utf-8')
- self.assertFileHandleOpenBehaviorsMatch(
- 'append', 'a', encoding='utf-8')
+ self.assertFileHandleOpenBehaviorsMatch("read", "r", encoding="utf-8")
+ self.assertFileHandleOpenBehaviorsMatch("write", "w", encoding="utf-8")
+ self.assertFileHandleOpenBehaviorsMatch("append", "a", encoding="utf-8")
def main(_):
unittest.main()
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
diff --git a/pyfakefs/tests/fake_open_test.py b/pyfakefs/tests/fake_open_test.py
index 9e942f9..d04bb79 100644
--- a/pyfakefs/tests/fake_open_test.py
+++ b/pyfakefs/tests/fake_open_test.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
#
# Copyright 2009 Google Inc. All Rights Reserved.
#
@@ -14,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Unit tests for fake_filesystem.FakeOsModule."""
+"""Unit tests for fake_open.FakeOsModule."""
import errno
import io
@@ -25,8 +24,9 @@ import sys
import time
import unittest
-from pyfakefs import fake_filesystem
-from pyfakefs.fake_filesystem import is_root, PERM_READ, FakeIoModule
+from pyfakefs import fake_filesystem, helpers
+from pyfakefs.helpers import is_root, IS_PYPY
+from pyfakefs.fake_io import FakeIoModule
from pyfakefs.fake_filesystem_unittest import PatchMode
from pyfakefs.tests.test_utils import RealFsTestCase
@@ -41,7 +41,7 @@ class FakeFileOpenTestBase(RealFsTestCase):
self.open = self.fake_io_module.open
def path_separator(self):
- return '!'
+ return "!"
class FakeFileOpenTest(FakeFileOpenTestBase):
@@ -55,49 +55,47 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
def test_open_no_parent_dir(self):
"""Expect raise when opening a file in a missing directory."""
- file_path = self.make_path('foo', 'bar.txt')
- self.assert_raises_os_error(errno.ENOENT, self.open, file_path, 'w')
+ file_path = self.make_path("foo", "bar.txt")
+ self.assert_raises_os_error(errno.ENOENT, self.open, file_path, "w")
def test_delete_on_close(self):
self.skip_real_fs()
- file_dir = 'boo'
- file_path = 'boo!far'
+ file_dir = "boo"
+ file_path = "boo!far"
self.os.mkdir(file_dir)
- self.open = fake_filesystem.FakeFileOpen(self.filesystem,
- delete_on_close=True)
- with self.open(file_path, 'w'):
+ self.open = fake_filesystem.FakeFileOpen(self.filesystem, delete_on_close=True)
+ with self.open(file_path, "w"):
self.assertTrue(self.filesystem.exists(file_path))
self.assertFalse(self.filesystem.exists(file_path))
def test_no_delete_on_close_by_default(self):
- file_path = self.make_path('czar')
- with self.open(file_path, 'w'):
+ file_path = self.make_path("czar")
+ with self.open(file_path, "w"):
self.assertTrue(self.os.path.exists(file_path))
self.assertTrue(self.os.path.exists(file_path))
def test_compatibility_of_with_statement(self):
self.skip_real_fs()
- self.open = fake_filesystem.FakeFileOpen(self.filesystem,
- delete_on_close=True)
- file_path = 'foo'
+ self.open = fake_filesystem.FakeFileOpen(self.filesystem, delete_on_close=True)
+ file_path = "foo"
self.assertFalse(self.os.path.exists(file_path))
- with self.open(file_path, 'w'):
+ with self.open(file_path, "w"):
self.assertTrue(self.os.path.exists(file_path))
# After the 'with' statement, the close() method should have been
# called.
self.assertFalse(self.os.path.exists(file_path))
def test_unicode_contents(self):
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
# note that this will work only if the string can be represented
# by the locale preferred encoding - which under Windows is
# usually not UTF-8, but something like Latin1, depending on the locale
- text_fractions = 'Ümläüts'
+ text_fractions = "Ümläüts"
try:
- with self.open(file_path, 'w') as f:
+ with self.open(file_path, "w") as f:
f.write(text_fractions)
except UnicodeEncodeError:
- # see https://github.com/jmcgeheeiv/pyfakefs/issues/623
+ # see https://github.com/pytest-dev/pyfakefs/issues/623
self.skipTest("This test does not work with an ASCII locale")
with self.open(file_path) as f:
@@ -105,67 +103,71 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
self.assertEqual(contents, text_fractions)
def test_byte_contents(self):
- file_path = self.make_path('foo')
- byte_fractions = b'\xe2\x85\x93 \xe2\x85\x94 \xe2\x85\x95 \xe2\x85\x96'
- with self.open(file_path, 'wb') as f:
+ file_path = self.make_path("foo")
+ byte_fractions = b"\xe2\x85\x93 \xe2\x85\x94 \xe2\x85\x95 \xe2\x85\x96"
+ with self.open(file_path, "wb") as f:
f.write(byte_fractions)
# the encoding has to be specified, otherwise the locale default
# is used which can be different on different systems
- with self.open(file_path, encoding='utf-8') as f:
+ with self.open(file_path, encoding="utf-8") as f:
contents = f.read()
- self.assertEqual(contents, byte_fractions.decode('utf-8'))
+ self.assertEqual(contents, byte_fractions.decode("utf-8"))
def test_write_str_read_bytes(self):
- file_path = self.make_path('foo')
- str_contents = 'Äsgül'
+ file_path = self.make_path("foo")
+ str_contents = "Äsgül"
try:
- with self.open(file_path, 'w') as f:
+ with self.open(file_path, "w") as f:
f.write(str_contents)
except UnicodeEncodeError:
- # see https://github.com/jmcgeheeiv/pyfakefs/issues/623
+ # see https://github.com/pytest-dev/pyfakefs/issues/623
self.skipTest("This test does not work with an ASCII locale")
- with self.open(file_path, 'rb') as f:
+ with self.open(file_path, "rb") as f:
contents = f.read()
- self.assertEqual(str_contents, contents.decode(
- locale.getpreferredencoding(False)))
+ self.assertEqual(
+ str_contents, contents.decode(locale.getpreferredencoding(False))
+ )
def test_open_valid_file(self):
contents = [
- 'I am he as\n',
- 'you are he as\n',
- 'you are me and\n',
- 'we are all together\n'
+ "I am he as\n",
+ "you are he as\n",
+ "you are me and\n",
+ "we are all together\n",
]
- file_path = self.make_path('bar.txt')
- self.create_file(file_path, contents=''.join(contents))
+ file_path = self.make_path("bar.txt")
+ self.create_file(file_path, contents="".join(contents))
with self.open(file_path) as fake_file:
self.assertEqual(contents, fake_file.readlines())
def test_open_valid_args(self):
contents = [
"Bang bang Maxwell's silver hammer\n",
- 'Came down on her head',
+ "Came down on her head",
]
- file_path = self.make_path('abbey_road', 'maxwell')
- self.create_file(file_path, contents=''.join(contents))
+ file_path = self.make_path("abbey_road", "maxwell")
+ self.create_file(file_path, contents="".join(contents))
with self.open(file_path, buffering=1) as f:
self.assertEqual(contents, f.readlines())
- with self.open(file_path, buffering=1,
- errors='strict', newline='\n', opener=None) as f:
- expected_contents = [contents[0][:-1] + self.os.linesep,
- contents[1]]
+ with self.open(
+ file_path, buffering=1, errors="strict", newline="\n", opener=None
+ ) as f:
+ expected_contents = [
+ contents[0][:-1] + self.os.linesep,
+ contents[1],
+ ]
self.assertEqual(expected_contents, f.readlines())
def test_open_valid_file_with_cwd(self):
contents = [
- 'I am he as\n',
- 'you are he as\n',
- 'you are me and\n',
- 'we are all together\n'
+ "I am he as\n",
+ "you are he as\n",
+ "you are me and\n",
+ "we are all together\n",
]
- file_path = self.make_path('bar.txt')
- self.create_file(file_path, contents=''.join(contents))
+ file_path = self.make_path("bar.txt")
+ self.create_file(file_path, contents="".join(contents))
self.os.chdir(self.base_path)
with self.open(file_path) as f:
self.assertEqual(contents, f.readlines())
@@ -173,49 +175,48 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
def test_iterate_over_file(self):
contents = [
"Bang bang Maxwell's silver hammer",
- 'Came down on her head',
+ "Came down on her head",
]
- file_path = self.make_path('abbey_road', 'maxwell')
- self.create_file(file_path, contents='\n'.join(contents))
+ file_path = self.make_path("abbey_road", "maxwell")
+ self.create_file(file_path, contents="\n".join(contents))
with self.open(file_path) as fake_file:
result = [line.rstrip() for line in fake_file]
self.assertEqual(contents, result)
def test_next_over_file(self):
- contents = [
- 'Live long\n',
- 'and prosper\n'
- ]
+ contents = ["Live long\n", "and prosper\n"]
result = []
- file_path = self.make_path('foo.txt')
- self.create_file(file_path, contents=''.join(contents))
+ file_path = self.make_path("foo.txt")
+ self.create_file(file_path, contents="".join(contents))
with self.open(file_path) as fake_file:
result.append(next(fake_file))
result.append(next(fake_file))
self.assertEqual(contents, result)
def test_open_directory_error(self):
- directory_path = self.make_path('foo')
+ directory_path = self.make_path("foo")
self.os.mkdir(directory_path)
if self.is_windows:
- self.assert_raises_os_error(errno.EACCES, self.open.__call__,
- directory_path)
+ self.assert_raises_os_error(
+ errno.EACCES, self.open.__call__, directory_path
+ )
else:
- self.assert_raises_os_error(errno.EISDIR, self.open.__call__,
- directory_path)
+ self.assert_raises_os_error(
+ errno.EISDIR, self.open.__call__, directory_path
+ )
def test_create_file_with_write(self):
contents = [
"Here comes the sun, little darlin'",
- 'Here comes the sun, and I say,',
+ "Here comes the sun, and I say,",
"It's alright",
]
- file_dir = self.make_path('abbey_road')
- file_path = self.os.path.join(file_dir, 'here_comes_the_sun')
+ file_dir = self.make_path("abbey_road")
+ file_path = self.os.path.join(file_dir, "here_comes_the_sun")
self.os.mkdir(file_dir)
- with self.open(file_path, 'w') as fake_file:
+ with self.open(file_path, "w") as fake_file:
for line in contents:
- fake_file.write(line + '\n')
+ fake_file.write(line + "\n")
with self.open(file_path) as fake_file:
result = [line.rstrip() for line in fake_file]
self.assertEqual(contents, result)
@@ -223,145 +224,141 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
def test_create_file_with_append(self):
contents = [
"Here comes the sun, little darlin'",
- 'Here comes the sun, and I say,',
+ "Here comes the sun, and I say,",
"It's alright",
]
- file_dir = self.make_path('abbey_road')
- file_path = self.os.path.join(file_dir, 'here_comes_the_sun')
+ file_dir = self.make_path("abbey_road")
+ file_path = self.os.path.join(file_dir, "here_comes_the_sun")
self.os.mkdir(file_dir)
- with self.open(file_path, 'a') as fake_file:
+ with self.open(file_path, "a") as fake_file:
for line in contents:
- fake_file.write(line + '\n')
+ fake_file.write(line + "\n")
with self.open(file_path) as fake_file:
result = [line.rstrip() for line in fake_file]
self.assertEqual(contents, result)
def test_exclusive_create_file_failure(self):
self.skip_if_symlink_not_supported()
- file_path = self.make_path('bar')
+ file_path = self.make_path("bar")
self.create_file(file_path)
- self.assert_raises_os_error(errno.EEXIST, self.open, file_path, 'x')
- self.assert_raises_os_error(errno.EEXIST, self.open, file_path, 'xb')
+ self.assert_raises_os_error(errno.EEXIST, self.open, file_path, "x")
+ self.assert_raises_os_error(errno.EEXIST, self.open, file_path, "xb")
def test_exclusive_create_file(self):
- file_dir = self.make_path('foo')
- file_path = self.os.path.join(file_dir, 'bar')
+ file_dir = self.make_path("foo")
+ file_path = self.os.path.join(file_dir, "bar")
self.os.mkdir(file_dir)
- contents = 'String contents'
- with self.open(file_path, 'x') as fake_file:
+ contents = "String contents"
+ with self.open(file_path, "x") as fake_file:
fake_file.write(contents)
with self.open(file_path) as fake_file:
self.assertEqual(contents, fake_file.read())
def test_exclusive_create_binary_file(self):
- file_dir = self.make_path('foo')
- file_path = self.os.path.join(file_dir, 'bar')
+ file_dir = self.make_path("foo")
+ file_path = self.os.path.join(file_dir, "bar")
self.os.mkdir(file_dir)
- contents = b'Binary contents'
- with self.open(file_path, 'xb') as fake_file:
+ contents = b"Binary contents"
+ with self.open(file_path, "xb") as fake_file:
fake_file.write(contents)
- with self.open(file_path, 'rb') as fake_file:
+ with self.open(file_path, "rb") as fake_file:
self.assertEqual(contents, fake_file.read())
def test_overwrite_existing_file(self):
- file_path = self.make_path('overwite')
- self.create_file(file_path, contents='To disappear')
+ file_path = self.make_path("overwrite")
+ self.create_file(file_path, contents="To disappear")
new_contents = [
- 'Only these lines',
- 'should be in the file.',
+ "Only these lines",
+ "should be in the file.",
]
- with self.open(file_path, 'w') as fake_file:
+ with self.open(file_path, "w") as fake_file:
for line in new_contents:
- fake_file.write(line + '\n')
+ fake_file.write(line + "\n")
with self.open(file_path) as fake_file:
result = [line.rstrip() for line in fake_file]
self.assertEqual(new_contents, result)
def test_append_existing_file(self):
- file_path = self.make_path('appendfile')
+ file_path = self.make_path("appendfile")
contents = [
- 'Contents of original file'
- 'Appended contents',
+ "Contents of original file" "Appended contents",
]
self.create_file(file_path, contents=contents[0])
- with self.open(file_path, 'a') as fake_file:
+ with self.open(file_path, "a") as fake_file:
for line in contents[1:]:
- fake_file.write(line + '\n')
+ fake_file.write(line + "\n")
with self.open(file_path) as fake_file:
result = [line.rstrip() for line in fake_file]
self.assertEqual(contents, result)
def test_open_with_wplus(self):
# set up
- file_path = self.make_path('wplus_file')
- self.create_file(file_path, contents='old contents')
+ file_path = self.make_path("wplus_file")
+ self.create_file(file_path, contents="old contents")
self.assertTrue(self.os.path.exists(file_path))
- with self.open(file_path, 'r') as fake_file:
- self.assertEqual('old contents', fake_file.read())
+ with self.open(file_path, "r") as fake_file:
+ self.assertEqual("old contents", fake_file.read())
# actual tests
- with self.open(file_path, 'w+') as fake_file:
- fake_file.write('new contents')
+ with self.open(file_path, "w+") as fake_file:
+ fake_file.write("new contents")
fake_file.seek(0)
- self.assertTrue('new contents', fake_file.read())
+ self.assertTrue("new contents", fake_file.read())
def test_open_with_wplus_truncation(self):
# set up
- file_path = self.make_path('wplus_file')
- self.create_file(file_path, contents='old contents')
+ file_path = self.make_path("wplus_file")
+ self.create_file(file_path, contents="old contents")
self.assertTrue(self.os.path.exists(file_path))
- with self.open(file_path, 'r') as fake_file:
- self.assertEqual('old contents', fake_file.read())
+ with self.open(file_path, "r") as fake_file:
+ self.assertEqual("old contents", fake_file.read())
# actual tests
- with self.open(file_path, 'w+') as fake_file:
+ with self.open(file_path, "w+") as fake_file:
fake_file.seek(0)
- self.assertEqual('', fake_file.read())
+ self.assertEqual("", fake_file.read())
def test_open_with_append_flag(self):
contents = [
- 'I am he as\n',
- 'you are he as\n',
- 'you are me and\n',
- 'we are all together\n'
- ]
- additional_contents = [
- 'These new lines\n',
- 'like you a lot.\n'
+ "I am he as\n",
+ "you are he as\n",
+ "you are me and\n",
+ "we are all together\n",
]
- file_path = self.make_path('appendfile')
- self.create_file(file_path, contents=''.join(contents))
- with self.open(file_path, 'a') as fake_file:
+ additional_contents = ["These new lines\n", "like you a lot.\n"]
+ file_path = self.make_path("appendfile")
+ self.create_file(file_path, contents="".join(contents))
+ with self.open(file_path, "a") as fake_file:
with self.assertRaises(io.UnsupportedOperation):
fake_file.read(0)
with self.assertRaises(io.UnsupportedOperation):
fake_file.readline()
- expected_len = len(''.join(contents))
+ expected_len = len("".join(contents))
expected_len += len(contents) * (len(self.os.linesep) - 1)
self.assertEqual(expected_len, fake_file.tell())
fake_file.seek(0)
self.assertEqual(0, fake_file.tell())
fake_file.writelines(additional_contents)
with self.open(file_path) as fake_file:
- self.assertEqual(
- contents + additional_contents, fake_file.readlines())
+ self.assertEqual(contents + additional_contents, fake_file.readlines())
def check_append_with_aplus(self):
- file_path = self.make_path('aplus_file')
- self.create_file(file_path, contents='old contents')
+ file_path = self.make_path("aplus_file")
+ self.create_file(file_path, contents="old contents")
self.assertTrue(self.os.path.exists(file_path))
- with self.open(file_path, 'r') as fake_file:
- self.assertEqual('old contents', fake_file.read())
+ with self.open(file_path, "r") as fake_file:
+ self.assertEqual("old contents", fake_file.read())
if self.filesystem:
# need to recreate FakeFileOpen for OS specific initialization
- self.open = fake_filesystem.FakeFileOpen(self.filesystem,
- delete_on_close=True)
- with self.open(file_path, 'a+') as fake_file:
+ self.open = fake_filesystem.FakeFileOpen(
+ self.filesystem, delete_on_close=True
+ )
+ with self.open(file_path, "a+") as fake_file:
self.assertEqual(12, fake_file.tell())
- fake_file.write('new contents')
+ fake_file.write("new contents")
self.assertEqual(24, fake_file.tell())
fake_file.seek(0)
- self.assertEqual('old contentsnew contents', fake_file.read())
+ self.assertEqual("old contentsnew contents", fake_file.read())
def test_append_with_aplus_mac_os(self):
self.check_macos_only()
@@ -373,43 +370,43 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
def test_append_with_aplus_read_with_loop(self):
# set up
- file_path = self.make_path('aplus_file')
- self.create_file(file_path, contents='old contents')
+ file_path = self.make_path("aplus_file")
+ self.create_file(file_path, contents="old contents")
self.assertTrue(self.os.path.exists(file_path))
- with self.open(file_path, 'r') as fake_file:
- self.assertEqual('old contents', fake_file.read())
+ with self.open(file_path, "r") as fake_file:
+ self.assertEqual("old contents", fake_file.read())
# actual tests
- with self.open(file_path, 'a+') as fake_file:
+ with self.open(file_path, "a+") as fake_file:
fake_file.seek(0)
- fake_file.write('new contents')
+ fake_file.write("new contents")
fake_file.seek(0)
for line in fake_file:
- self.assertEqual('old contentsnew contents', line)
+ self.assertEqual("old contentsnew contents", line)
def test_read_empty_file_with_aplus(self):
- file_path = self.make_path('aplus_file')
- with self.open(file_path, 'a+') as fake_file:
- self.assertEqual('', fake_file.read())
+ file_path = self.make_path("aplus_file")
+ with self.open(file_path, "a+") as fake_file:
+ self.assertEqual("", fake_file.read())
def test_read_with_rplus(self):
# set up
- file_path = self.make_path('rplus_file')
- self.create_file(file_path, contents='old contents here')
+ file_path = self.make_path("rplus_file")
+ self.create_file(file_path, contents="old contents here")
self.assertTrue(self.os.path.exists(file_path))
- with self.open(file_path, 'r') as fake_file:
- self.assertEqual('old contents here', fake_file.read())
+ with self.open(file_path, "r") as fake_file:
+ self.assertEqual("old contents here", fake_file.read())
# actual tests
- with self.open(file_path, 'r+') as fake_file:
- self.assertEqual('old contents here', fake_file.read())
+ with self.open(file_path, "r+") as fake_file:
+ self.assertEqual("old contents here", fake_file.read())
fake_file.seek(0)
- fake_file.write('new contents')
+ fake_file.write("new contents")
fake_file.seek(0)
- self.assertEqual('new contents here', fake_file.read())
+ self.assertEqual("new contents here", fake_file.read())
def create_with_permission(self, file_path, perm_bits):
self.create_file(file_path)
self.os.chmod(file_path, perm_bits)
- if perm_bits & PERM_READ:
+ if perm_bits & helpers.PERM_READ:
st = self.os.stat(file_path)
self.assert_mode_equal(perm_bits, st.st_mode)
self.assertTrue(st.st_mode & stat.S_IFREG)
@@ -418,89 +415,87 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
def test_open_flags700(self):
# set up
self.check_posix_only()
- file_path = self.make_path('target_file')
+ file_path = self.make_path("target_file")
self.create_with_permission(file_path, 0o700)
# actual tests
- self.open(file_path, 'r').close()
- self.open(file_path, 'w').close()
- self.open(file_path, 'w+').close()
+ self.open(file_path, "r").close()
+ self.open(file_path, "w").close()
+ self.open(file_path, "w+").close()
with self.assertRaises(ValueError):
- self.open(file_path, 'INV')
+ self.open(file_path, "INV")
def test_open_flags400(self):
# set up
self.check_posix_only()
- file_path = self.make_path('target_file')
+ file_path = self.make_path("target_file")
self.create_with_permission(file_path, 0o400)
# actual tests
- self.open(file_path, 'r').close()
+ self.open(file_path, "r").close()
if not is_root():
- self.assert_raises_os_error(
- errno.EACCES, self.open, file_path, 'w')
- self.assert_raises_os_error(
- errno.EACCES, self.open, file_path, 'w+')
+ self.assert_raises_os_error(errno.EACCES, self.open, file_path, "w")
+ self.assert_raises_os_error(errno.EACCES, self.open, file_path, "w+")
else:
- self.open(file_path, 'w').close()
- self.open(file_path, 'w+').close()
+ self.open(file_path, "w").close()
+ self.open(file_path, "w+").close()
def test_open_flags200(self):
# set up
self.check_posix_only()
- file_path = self.make_path('target_file')
+ file_path = self.make_path("target_file")
self.create_with_permission(file_path, 0o200)
# actual tests
- self.open(file_path, 'w').close()
+ self.open(file_path, "w").close()
if not is_root():
with self.assertRaises(OSError):
- self.open(file_path, 'r')
+ self.open(file_path, "r")
with self.assertRaises(OSError):
- self.open(file_path, 'w+')
+ self.open(file_path, "w+")
else:
- self.open(file_path, 'r').close()
- self.open(file_path, 'w+').close()
+ self.open(file_path, "r").close()
+ self.open(file_path, "w+").close()
def test_open_flags100(self):
# set up
self.check_posix_only()
- file_path = self.make_path('target_file')
+ file_path = self.make_path("target_file")
self.create_with_permission(file_path, 0o100)
# actual tests
if not is_root():
with self.assertRaises(OSError):
- self.open(file_path, 'r')
+ self.open(file_path, "r")
with self.assertRaises(OSError):
- self.open(file_path, 'w')
+ self.open(file_path, "w")
with self.assertRaises(OSError):
- self.open(file_path, 'w+')
+ self.open(file_path, "w+")
else:
- self.open(file_path, 'r').close()
- self.open(file_path, 'w').close()
- self.open(file_path, 'w+').close()
+ self.open(file_path, "r").close()
+ self.open(file_path, "w").close()
+ self.open(file_path, "w+").close()
def test_follow_link_read(self):
self.skip_if_symlink_not_supported()
- link_path = self.make_path('foo', 'bar', 'baz')
- target = self.make_path('tarJAY')
- target_contents = 'real baz contents'
+ link_path = self.make_path("foo", "bar", "baz")
+ target = self.make_path("tarJAY")
+ target_contents = "real baz contents"
self.create_file(target, contents=target_contents)
self.create_symlink(link_path, target)
self.assert_equal_paths(target, self.os.readlink(link_path))
- fh = self.open(link_path, 'r')
+ fh = self.open(link_path, "r")
got_contents = fh.read()
fh.close()
self.assertEqual(target_contents, got_contents)
def test_follow_link_write(self):
self.skip_if_symlink_not_supported()
- link_path = self.make_path('foo', 'bar', 'TBD')
- target = self.make_path('tarJAY')
- target_contents = 'real baz contents'
+ link_path = self.make_path("foo", "bar", "TBD")
+ target = self.make_path("tarJAY")
+ target_contents = "real baz contents"
self.create_symlink(link_path, target)
self.assertFalse(self.os.path.exists(target))
- with self.open(link_path, 'w') as fh:
+ with self.open(link_path, "w") as fh:
fh.write(target_contents)
- with self.open(target, 'r') as fh:
+ with self.open(target, "r") as fh:
got_contents = fh.read()
self.assertEqual(target_contents, got_contents)
@@ -508,39 +503,41 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
# Test a link in the middle of of a file path.
self.skip_if_symlink_not_supported()
link_path = self.os.path.join(
- self.base_path, 'foo', 'build', 'local_machine', 'output', '1')
- target = self.make_path('tmp', 'output', '1')
- self.create_dir(self.make_path('tmp', 'output'))
- self.create_symlink(self.os.path.join(
- self.base_path, 'foo', 'build', 'local_machine'),
- self.make_path('tmp'))
+ self.base_path, "foo", "build", "local_machine", "output", "1"
+ )
+ target = self.make_path("tmp", "output", "1")
+ self.create_dir(self.make_path("tmp", "output"))
+ self.create_symlink(
+ self.os.path.join(self.base_path, "foo", "build", "local_machine"),
+ self.make_path("tmp"),
+ )
self.assertFalse(self.os.path.exists(link_path))
self.assertFalse(self.os.path.exists(target))
- target_contents = 'real baz contents'
- with self.open(link_path, 'w') as fh:
+ target_contents = "real baz contents"
+ with self.open(link_path, "w") as fh:
fh.write(target_contents)
- with self.open(target, 'r') as fh:
+ with self.open(target, "r") as fh:
got_contents = fh.read()
self.assertEqual(target_contents, got_contents)
def test_open_raises_on_symlink_loop(self):
# Regression test for #274
self.check_posix_only()
- file_dir = self.make_path('foo')
+ file_dir = self.make_path("foo")
self.os.mkdir(file_dir)
- file_path = self.os.path.join(file_dir, 'baz')
+ file_path = self.os.path.join(file_dir, "baz")
self.os.symlink(file_path, file_path)
self.assert_raises_os_error(errno.ELOOP, self.open, file_path)
def test_file_descriptors_for_different_files(self):
- first_path = self.make_path('some_file1')
- self.create_file(first_path, contents='contents here1')
- second_path = self.make_path('some_file2')
- self.create_file(second_path, contents='contents here2')
- third_path = self.make_path('some_file3')
- self.create_file(third_path, contents='contents here3')
+ first_path = self.make_path("some_file1")
+ self.create_file(first_path, contents="contents here1")
+ second_path = self.make_path("some_file2")
+ self.create_file(second_path, contents="contents here2")
+ third_path = self.make_path("some_file3")
+ self.create_file(third_path, contents="contents here3")
with self.open(first_path) as fake_file1:
with self.open(second_path) as fake_file2:
@@ -550,10 +547,10 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
self.assertGreater(fake_file3.fileno(), fileno2)
def test_file_descriptors_for_the_same_file_are_different(self):
- first_path = self.make_path('some_file1')
- self.create_file(first_path, contents='contents here1')
- second_path = self.make_path('some_file2')
- self.create_file(second_path, contents='contents here2')
+ first_path = self.make_path("some_file1")
+ self.create_file(first_path, contents="contents here1")
+ second_path = self.make_path("some_file2")
+ self.create_file(second_path, contents="contents here2")
with self.open(first_path) as fake_file1:
with self.open(second_path) as fake_file2:
with self.open(first_path) as fake_file1a:
@@ -562,24 +559,24 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
self.assertGreater(fake_file1a.fileno(), fileno2)
def test_reused_file_descriptors_do_not_affect_others(self):
- first_path = self.make_path('some_file1')
- self.create_file(first_path, contents='contents here1')
- second_path = self.make_path('some_file2')
- self.create_file(second_path, contents='contents here2')
- third_path = self.make_path('some_file3')
- self.create_file(third_path, contents='contents here3')
-
- with self.open(first_path, 'r') as fake_file1:
- with self.open(second_path, 'r') as fake_file2:
- fake_file3 = self.open(third_path, 'r')
- fake_file1a = self.open(first_path, 'r')
+ first_path = self.make_path("some_file1")
+ self.create_file(first_path, contents="contents here1")
+ second_path = self.make_path("some_file2")
+ self.create_file(second_path, contents="contents here2")
+ third_path = self.make_path("some_file3")
+ self.create_file(third_path, contents="contents here3")
+
+ with self.open(first_path, "r") as fake_file1:
+ with self.open(second_path, "r") as fake_file2:
+ fake_file3 = self.open(third_path, "r")
+ fake_file1a = self.open(first_path, "r")
fileno1 = fake_file1.fileno()
fileno2 = fake_file2.fileno()
fileno3 = fake_file3.fileno()
fileno4 = fake_file1a.fileno()
- with self.open(second_path, 'r') as fake_file2:
- with self.open(first_path, 'r') as fake_file1b:
+ with self.open(second_path, "r") as fake_file2:
+ with self.open(first_path, "r") as fake_file1b:
self.assertEqual(fileno1, fake_file2.fileno())
self.assertEqual(fileno2, fake_file1b.fileno())
self.assertEqual(fileno3, fake_file3.fileno())
@@ -588,13 +585,18 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
fake_file1a.close()
def test_intertwined_read_write(self):
- file_path = self.make_path('some_file')
+ file_path = self.make_path("some_file")
self.create_file(file_path)
- with self.open(file_path, 'a') as writer:
- with self.open(file_path, 'r') as reader:
- writes = ['hello', 'world\n', 'somewhere\nover', 'the\n',
- 'rainbow']
+ with self.open(file_path, "a") as writer:
+ with self.open(file_path, "r") as reader:
+ writes = [
+ "hello",
+ "world\n",
+ "somewhere\nover",
+ "the\n",
+ "rainbow",
+ ]
reads = []
# when writes are flushes, they are piped to the reader
for write in writes:
@@ -603,22 +605,22 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
reads.append(reader.read())
reader.flush()
self.assertEqual(writes, reads)
- writes = ['nothing', 'to\nsee', 'here']
+ writes = ["nothing", "to\nsee", "here"]
reads = []
# when writes are not flushed, the reader doesn't read
# anything new
for write in writes:
writer.write(write)
reads.append(reader.read())
- self.assertEqual(['' for _ in writes], reads)
+ self.assertEqual(["" for _ in writes], reads)
def test_intertwined_read_write_python3_str(self):
- file_path = self.make_path('some_file')
+ file_path = self.make_path("some_file")
self.create_file(file_path)
- with self.open(file_path, 'a', encoding='utf-8') as writer:
- with self.open(file_path, 'r', encoding='utf-8') as reader:
- writes = ['привет', 'мир\n', 'где-то\nза', 'радугой']
+ with self.open(file_path, "a", encoding="utf-8") as writer:
+ with self.open(file_path, "r", encoding="utf-8") as reader:
+ writes = ["привет", "мир\n", "где-то\nза", "радугой"]
reads = []
# when writes are flushes, they are piped to the reader
for write in writes:
@@ -627,36 +629,36 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
reads.append(reader.read())
reader.flush()
self.assertEqual(writes, reads)
- writes = ['ничего', 'не\nвидно']
+ writes = ["ничего", "не\nвидно"]
reads = []
# when writes are not flushed, the reader doesn't
# read anything new
for write in writes:
writer.write(write)
reads.append(reader.read())
- self.assertEqual(['' for _ in writes], reads)
+ self.assertEqual(["" for _ in writes], reads)
def test_open_io_errors(self):
- file_path = self.make_path('some_file')
+ file_path = self.make_path("some_file")
self.create_file(file_path)
- with self.open(file_path, 'a') as fh:
+ with self.open(file_path, "a") as fh:
with self.assertRaises(OSError):
fh.read()
with self.assertRaises(OSError):
fh.readlines()
- with self.open(file_path, 'w') as fh:
+ with self.open(file_path, "w") as fh:
with self.assertRaises(OSError):
fh.read()
with self.assertRaises(OSError):
fh.readlines()
- with self.open(file_path, 'r') as fh:
+ with self.open(file_path, "r") as fh:
with self.assertRaises(OSError):
fh.truncate()
with self.assertRaises(OSError):
- fh.write('contents')
+ fh.write("contents")
with self.assertRaises(OSError):
- fh.writelines(['con', 'tents'])
+ fh.writelines(["con", "tents"])
def _iterator_open(mode):
with self.open(file_path, mode) as f:
@@ -664,28 +666,28 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
pass
with self.assertRaises(OSError):
- _iterator_open('w')
+ _iterator_open("w")
with self.assertRaises(OSError):
- _iterator_open('a')
+ _iterator_open("a")
def test_open_raises_io_error_if_parent_is_file_posix(self):
self.check_posix_only()
- file_path = self.make_path('bar')
+ file_path = self.make_path("bar")
self.create_file(file_path)
- file_path = self.os.path.join(file_path, 'baz')
- self.assert_raises_os_error(errno.ENOTDIR, self.open, file_path, 'w')
+ file_path = self.os.path.join(file_path, "baz")
+ self.assert_raises_os_error(errno.ENOTDIR, self.open, file_path, "w")
def test_open_raises_io_error_if_parent_is_file_windows(self):
self.check_windows_only()
- file_path = self.make_path('bar')
+ file_path = self.make_path("bar")
self.create_file(file_path)
- file_path = self.os.path.join(file_path, 'baz')
- self.assert_raises_os_error(errno.ENOENT, self.open, file_path, 'w')
+ file_path = self.os.path.join(file_path, "baz")
+ self.assert_raises_os_error(errno.ENOENT, self.open, file_path, "w")
def check_open_with_trailing_sep(self, error_nr):
# regression test for #362
- path = self.make_path('foo') + self.os.path.sep
- self.assert_raises_os_error(error_nr, self.open, path, 'w')
+ path = self.make_path("foo") + self.os.path.sep
+ self.assert_raises_os_error(error_nr, self.open, path, "w")
def test_open_with_trailing_sep_linux(self):
self.check_linux_only()
@@ -701,56 +703,55 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
def test_can_read_from_block_device(self):
self.skip_real_fs()
- device_path = 'device'
- self.filesystem.create_file(device_path, stat.S_IFBLK
- | fake_filesystem.PERM_ALL)
- with self.open(device_path, 'r') as fh:
- self.assertEqual('', fh.read())
+ device_path = "device"
+ self.filesystem.create_file(device_path, stat.S_IFBLK | helpers.PERM_ALL)
+ with self.open(device_path, "r") as fh:
+ self.assertEqual("", fh.read())
def test_truncate_flushes_contents(self):
# Regression test for #285
- file_path = self.make_path('baz')
+ file_path = self.make_path("baz")
self.create_file(file_path)
- with self.open(file_path, 'w') as f0:
- f0.write('test')
+ with self.open(file_path, "w") as f0:
+ f0.write("test")
f0.truncate()
self.assertEqual(4, self.os.path.getsize(file_path))
def test_update_other_instances_of_same_file_on_flush(self):
# Regression test for #302
- file_path = self.make_path('baz')
- with self.open(file_path, 'w') as f0:
- with self.open(file_path, 'w') as f1:
- f0.write('test')
+ file_path = self.make_path("baz")
+ with self.open(file_path, "w") as f0:
+ with self.open(file_path, "w") as f1:
+ f0.write("test")
f0.truncate()
f1.flush()
self.assertEqual(4, self.os.path.getsize(file_path))
def test_getsize_after_truncate(self):
# Regression test for #412
- file_path = self.make_path('foo')
- with self.open(file_path, 'a') as f:
- f.write('a')
+ file_path = self.make_path("foo")
+ with self.open(file_path, "a") as f:
+ f.write("a")
f.seek(0)
f.truncate()
- f.write('b')
+ f.write("b")
f.truncate()
self.assertEqual(1, self.os.path.getsize(file_path))
self.assertEqual(1, self.os.stat(file_path).st_size)
def test_st_size_after_truncate(self):
# Regression test for #412
- file_path = self.make_path('foo')
- with self.open(file_path, 'a') as f:
- f.write('a')
+ file_path = self.make_path("foo")
+ with self.open(file_path, "a") as f:
+ f.write("a")
f.truncate()
- f.write('b')
+ f.write("b")
f.truncate()
self.assertEqual(2, self.os.stat(file_path).st_size)
def test_that_read_over_end_does_not_reset_position(self):
# Regression test for #286
- file_path = self.make_path('baz')
+ file_path = self.make_path("baz")
self.create_file(file_path)
with self.open(file_path) as f0:
f0.seek(2)
@@ -760,15 +761,15 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
def test_accessing_closed_file_raises(self):
# Regression test for #275, #280
if self.is_pypy:
- raise unittest.SkipTest('Different exceptions with PyPy')
- file_path = self.make_path('foo')
- self.create_file(file_path, contents=b'test')
- fake_file = self.open(file_path, 'r')
+ raise unittest.SkipTest("Different exceptions with PyPy")
+ file_path = self.make_path("foo")
+ self.create_file(file_path, contents=b"test")
+ fake_file = self.open(file_path, "r")
fake_file.close()
with self.assertRaises(ValueError):
fake_file.read(1)
with self.assertRaises(ValueError):
- fake_file.write('a')
+ fake_file.write("a")
with self.assertRaises(ValueError):
fake_file.readline()
with self.assertRaises(ValueError):
@@ -783,74 +784,74 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
def test_accessing_open_file_with_another_handle_raises(self):
# Regression test for #282
if self.is_pypy:
- raise unittest.SkipTest('Different exceptions with PyPy')
- file_path = self.make_path('foo')
+ raise unittest.SkipTest("Different exceptions with PyPy")
+ file_path = self.make_path("foo")
f0 = self.os.open(file_path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
- fake_file = self.open(file_path, 'r')
+ fake_file = self.open(file_path, "r")
fake_file.close()
with self.assertRaises(ValueError):
fake_file.read(1)
with self.assertRaises(ValueError):
- fake_file.write('a')
+ fake_file.write("a")
self.os.close(f0)
def test_tell_flushes_under_mac_os(self):
# Regression test for #288
self.check_macos_only()
- file_path = self.make_path('foo')
- with self.open(file_path, 'w') as f0:
- f0.write('test')
+ file_path = self.make_path("foo")
+ with self.open(file_path, "w") as f0:
+ f0.write("test")
self.assertEqual(4, f0.tell())
self.assertEqual(4, self.os.path.getsize(file_path))
def test_tell_flushes_in_python3(self):
# Regression test for #288
self.check_linux_and_windows()
- file_path = self.make_path('foo')
- with self.open(file_path, 'w') as f0:
- f0.write('test')
+ file_path = self.make_path("foo")
+ with self.open(file_path, "w") as f0:
+ f0.write("test")
self.assertEqual(4, f0.tell())
self.assertEqual(4, self.os.path.getsize(file_path))
def test_read_flushes_under_posix(self):
# Regression test for #278
self.check_posix_only()
- file_path = self.make_path('foo')
- with self.open(file_path, 'a+') as f0:
- f0.write('test')
- self.assertEqual('', f0.read())
+ file_path = self.make_path("foo")
+ with self.open(file_path, "a+") as f0:
+ f0.write("test")
+ self.assertEqual("", f0.read())
self.assertEqual(4, self.os.path.getsize(file_path))
def test_read_flushes_under_windows_in_python3(self):
# Regression test for #278
self.check_windows_only()
- file_path = self.make_path('foo')
- with self.open(file_path, 'w+') as f0:
- f0.write('test')
+ file_path = self.make_path("foo")
+ with self.open(file_path, "w+") as f0:
+ f0.write("test")
f0.read()
self.assertEqual(4, self.os.path.getsize(file_path))
def test_seek_flushes(self):
# Regression test for #290
- file_path = self.make_path('foo')
- with self.open(file_path, 'w') as f0:
- f0.write('test')
+ file_path = self.make_path("foo")
+ with self.open(file_path, "w") as f0:
+ f0.write("test")
self.assertEqual(0, self.os.path.getsize(file_path))
f0.seek(3)
self.assertEqual(4, self.os.path.getsize(file_path))
def test_truncate_flushes(self):
# Regression test for #291
- file_path = self.make_path('foo')
- with self.open(file_path, 'a') as f0:
- f0.write('test')
+ file_path = self.make_path("foo")
+ with self.open(file_path, "a") as f0:
+ f0.write("test")
self.assertEqual(0, self.os.path.getsize(file_path))
f0.truncate()
self.assertEqual(4, self.os.path.getsize(file_path))
def check_seek_outside_and_truncate_sets_size(self, mode):
# Regression test for #294 and #296
- file_path = self.make_path('baz')
+ file_path = self.make_path("baz")
with self.open(file_path, mode) as f0:
f0.seek(1)
f0.truncate()
@@ -862,15 +863,15 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
def test_seek_outside_and_truncate_sets_size_in_write_mode(self):
# Regression test for #294
- self.check_seek_outside_and_truncate_sets_size('w')
+ self.check_seek_outside_and_truncate_sets_size("w")
def test_seek_outside_and_truncate_sets_size_in_append_mode(self):
# Regression test for #295
- self.check_seek_outside_and_truncate_sets_size('a')
+ self.check_seek_outside_and_truncate_sets_size("a")
def test_closed(self):
- file_path = self.make_path('foo')
- f = self.open(file_path, 'w')
+ file_path = self.make_path("foo")
+ f = self.open(file_path, "w")
self.assertFalse(f.closed)
f.close()
self.assertTrue(f.closed)
@@ -881,65 +882,65 @@ class FakeFileOpenTest(FakeFileOpenTestBase):
def test_closing_closed_file_does_nothing(self):
# Regression test for #299
- file_path = self.make_path('baz')
- f0 = self.open(file_path, 'w')
+ file_path = self.make_path("baz")
+ f0 = self.open(file_path, "w")
f0.close()
with self.open(file_path) as f1:
# would close f1 if not handled
f0.close()
- self.assertEqual('', f1.read())
+ self.assertEqual("", f1.read())
def test_closing_file_with_different_close_mode(self):
self.skip_real_fs()
- filename = self.make_path('test.txt')
+ filename = self.make_path("test.txt")
fd = self.os.open(filename, os.O_CREAT | os.O_RDWR)
file_obj = self.filesystem.get_object(filename)
- with self.open(fd, 'wb', closefd=False) as fp:
- fp.write(b'test')
+ with self.open(fd, "wb", closefd=False) as fp:
+ fp.write(b"test")
self.assertTrue(self.filesystem.has_open_file(file_obj))
self.os.close(fd)
self.assertFalse(self.filesystem.has_open_file(file_obj))
def test_truncate_flushes_zeros(self):
# Regression test for #301
- file_path = self.make_path('baz')
- with self.open(file_path, 'w') as f0:
+ file_path = self.make_path("baz")
+ with self.open(file_path, "w") as f0:
with self.open(file_path) as f1:
f0.seek(1)
f0.truncate()
- self.assertEqual('\0', f1.read())
+ self.assertEqual("\0", f1.read())
def test_byte_filename(self):
- file_path = self.make_path(b'test')
- with self.open(file_path, 'wb') as f:
- f.write(b'test')
- with self.open(file_path, 'rb') as f:
- self.assertEqual(b'test', f.read())
+ file_path = self.make_path(b"test")
+ with self.open(file_path, "wb") as f:
+ f.write(b"test")
+ with self.open(file_path, "rb") as f:
+ self.assertEqual(b"test", f.read())
def test_unicode_filename(self):
- file_path = self.make_path('тест')
- with self.open(file_path, 'wb') as f:
- f.write(b'test')
- with self.open(file_path, 'rb') as f:
- self.assertEqual(b'test', f.read())
+ file_path = self.make_path("тест")
+ with self.open(file_path, "wb") as f:
+ f.write(b"test")
+ with self.open(file_path, "rb") as f:
+ self.assertEqual(b"test", f.read())
def test_write_devnull(self):
- for mode in ('r+', 'w', 'w+', 'a', 'a+'):
+ for mode in ("r+", "w", "w+", "a", "a+"):
with self.open(self.os.devnull, mode) as f:
- f.write('test')
+ f.write("test")
with self.open(self.os.devnull) as f:
- self.assertEqual('', f.read())
+ self.assertEqual("", f.read())
def test_utf16_text(self):
# regression test for #574
- file_path = self.make_path('foo')
- with self.open(file_path, "w", encoding='utf-16') as f:
+ file_path = self.make_path("foo")
+ with self.open(file_path, "w", encoding="utf-16") as f:
assert f.write("1") == 1
- with self.open(file_path, "a", encoding='utf-16') as f:
+ with self.open(file_path, "a", encoding="utf-16") as f:
assert f.write("2") == 1
- with self.open(file_path, "r", encoding='utf-16') as f:
+ with self.open(file_path, "r", encoding="utf-16") as f:
text = f.read()
assert text == "12"
@@ -949,10 +950,100 @@ class RealFileOpenTest(FakeFileOpenTest):
return True
-@unittest.skipIf(sys.version_info < (3, 8),
- 'open_code only present since Python 3.8')
-class FakeFilePatchedOpenCodeTest(FakeFileOpenTestBase):
+class FakeFileOpenWithOpenerTest(FakeFileOpenTestBase):
+ def opener(self, path, flags):
+ return self.os.open(path, flags)
+
+ def test_use_opener_with_read(self):
+ file_path = self.make_path("foo")
+ self.create_file(file_path, contents="test")
+ with self.open(file_path, opener=self.opener) as f:
+ assert f.read() == "test"
+ with self.assertRaises(OSError):
+ f.write("foo")
+
+ def test_use_opener_with_read_plus(self):
+ file_path = self.make_path("foo")
+ self.create_file(file_path, contents="test")
+ with self.open(file_path, "r+", opener=self.opener) as f:
+ assert f.read() == "test"
+ assert f.write("bar") == 3
+ with self.open(file_path) as f:
+ assert f.read() == "testbar"
+
+ def test_use_opener_with_write(self):
+ file_path = self.make_path("foo")
+ self.create_file(file_path, contents="foo")
+ with self.open(file_path, "w", opener=self.opener) as f:
+ with self.assertRaises(OSError):
+ f.read()
+ assert f.write("bar") == 3
+ with self.open(file_path) as f:
+ assert f.read() == "bar"
+
+ def test_use_opener_with_write_plus(self):
+ file_path = self.make_path("foo")
+ self.create_file(file_path, contents="test")
+ with self.open(file_path, "w+", opener=self.opener) as f:
+ assert f.read() == ""
+ assert f.write("bar") == 3
+ with self.open(file_path) as f:
+ assert f.read() == "bar"
+
+ def test_use_opener_with_append(self):
+ file_path = self.make_path("foo")
+ self.create_file(file_path, contents="foo")
+ with self.open(file_path, "a", opener=self.opener) as f:
+ assert f.write("bar") == 3
+ with self.assertRaises(OSError):
+ f.read()
+ with self.open(file_path) as f:
+ assert f.read() == "foobar"
+
+ def test_use_opener_with_append_plus(self):
+ file_path = self.make_path("foo")
+ self.create_file(file_path, contents="foo")
+ with self.open(file_path, "a+", opener=self.opener) as f:
+ assert f.read() == ""
+ assert f.write("bar") == 3
+ with self.open(file_path) as f:
+ assert f.read() == "foobar"
+
+ def test_use_opener_with_exclusive_write(self):
+ file_path = self.make_path("foo")
+ self.create_file(file_path, contents="test")
+ with self.assertRaises(OSError):
+ self.open(file_path, "x", opener=self.opener)
+
+ file_path = self.make_path("bar")
+ with self.open(file_path, "x", opener=self.opener) as f:
+ assert f.write("bar") == 3
+ with self.assertRaises(OSError):
+ f.read()
+ with self.open(file_path) as f:
+ assert f.read() == "bar"
+
+ def test_use_opener_with_exclusive_plus(self):
+ file_path = self.make_path("foo")
+ self.create_file(file_path, contents="test")
+ with self.assertRaises(OSError):
+ self.open(file_path, "x+", opener=self.opener)
+ file_path = self.make_path("bar")
+ with self.open(file_path, "x+", opener=self.opener) as f:
+ assert f.write("bar") == 3
+ assert f.read() == ""
+ with self.open(file_path) as f:
+ assert f.read() == "bar"
+
+
+class RealFileOpenWithOpenerTest(FakeFileOpenWithOpenerTest):
+ def use_real_fs(self):
+ return True
+
+
+@unittest.skipIf(sys.version_info < (3, 8), "open_code only present since Python 3.8")
+class FakeFilePatchedOpenCodeTest(FakeFileOpenTestBase):
def setUp(self):
super(FakeFilePatchedOpenCodeTest, self).setUp()
if self.use_real_fs():
@@ -966,13 +1057,22 @@ class FakeFilePatchedOpenCodeTest(FakeFileOpenTestBase):
self.filesystem.patch_open_code = False
super(FakeFilePatchedOpenCodeTest, self).tearDown()
+ @unittest.skipIf(IS_PYPY, "Different behavior in PyPy")
def test_invalid_path(self):
with self.assertRaises(TypeError):
self.open_code(4)
+ @unittest.skipIf(not IS_PYPY, "Different behavior in PyPy")
+ def test_open_code_fd_pypy(self):
+ file_path = self.make_path("foo")
+ self.create_file(file_path, contents="test")
+ fd = self.os.open(file_path, os.O_RDONLY)
+ with self.open_code(fd) as f:
+ assert f.read() == b"test"
+
def test_byte_contents_open_code(self):
- byte_fractions = b'\xe2\x85\x93 \xe2\x85\x94 \xe2\x85\x95 \xe2\x85\x96'
- file_path = self.make_path('foo')
+ byte_fractions = b"\xe2\x85\x93 \xe2\x85\x94 \xe2\x85\x95 \xe2\x85\x96"
+ file_path = self.make_path("foo")
self.create_file(file_path, contents=byte_fractions)
with self.open_code(file_path) as f:
contents = f.read()
@@ -990,10 +1090,8 @@ class RealPatchedFileOpenCodeTest(FakeFilePatchedOpenCodeTest):
return True
-@unittest.skipIf(sys.version_info < (3, 8),
- 'open_code only present since Python 3.8')
+@unittest.skipIf(sys.version_info < (3, 8), "open_code only present since Python 3.8")
class FakeFileUnpatchedOpenCodeTest(FakeFileOpenTestBase):
-
def setUp(self):
super(FakeFileUnpatchedOpenCodeTest, self).setUp()
if self.use_real_fs():
@@ -1001,6 +1099,7 @@ class FakeFileUnpatchedOpenCodeTest(FakeFileOpenTestBase):
else:
self.open_code = self.fake_io_module.open_code
+ @unittest.skipIf(IS_PYPY, "Different behavior in PyPy")
def test_invalid_path(self):
with self.assertRaises(TypeError):
self.open_code(4)
@@ -1018,8 +1117,8 @@ class RealUnpatchedFileOpenCodeTest(FakeFileUnpatchedOpenCodeTest):
return True
def test_byte_contents_open_code(self):
- byte_fractions = b'\xe2\x85\x93 \xe2\x85\x94 \xe2\x85\x95 \xe2\x85\x96'
- file_path = self.make_path('foo')
+ byte_fractions = b"\xe2\x85\x93 \xe2\x85\x94 \xe2\x85\x95 \xe2\x85\x96"
+ file_path = self.make_path("foo")
self.create_file(file_path, contents=byte_fractions)
with self.open_code(file_path) as f:
contents = f.read()
@@ -1029,62 +1128,62 @@ class RealUnpatchedFileOpenCodeTest(FakeFileUnpatchedOpenCodeTest):
class BufferingModeTest(FakeFileOpenTestBase):
def test_no_buffering(self):
file_path = self.make_path("buffertest.bin")
- with self.open(file_path, 'wb', buffering=0) as f:
- f.write(b'a' * 128)
+ with self.open(file_path, "wb", buffering=0) as f:
+ f.write(b"a" * 128)
with self.open(file_path, "rb") as r:
x = r.read()
- self.assertEqual(b'a' * 128, x)
+ self.assertEqual(b"a" * 128, x)
def test_no_buffering_not_allowed_in_textmode(self):
file_path = self.make_path("buffertest.txt")
with self.assertRaises(ValueError):
- self.open(file_path, 'w', buffering=0)
+ self.open(file_path, "w", buffering=0)
def test_default_buffering_no_flush(self):
file_path = self.make_path("buffertest.bin")
- with self.open(file_path, 'wb') as f:
- f.write(b'a' * 2048)
+ with self.open(file_path, "wb") as f:
+ f.write(b"a" * 2048)
with self.open(file_path, "rb") as r:
x = r.read()
- self.assertEqual(b'', x)
+ self.assertEqual(b"", x)
with self.open(file_path, "rb") as r:
x = r.read()
- self.assertEqual(b'a' * 2048, x)
+ self.assertEqual(b"a" * 2048, x)
def test_default_buffering_flush(self):
file_path = self.make_path("buffertest.bin")
- with self.open(file_path, 'wb') as f:
- f.write(b'a' * 2048)
+ with self.open(file_path, "wb") as f:
+ f.write(b"a" * 2048)
f.flush()
with self.open(file_path, "rb") as r:
x = r.read()
- self.assertEqual(b'a' * 2048, x)
+ self.assertEqual(b"a" * 2048, x)
def test_writing_with_specific_buffer(self):
file_path = self.make_path("buffertest.bin")
- with self.open(file_path, 'wb', buffering=512) as f:
- f.write(b'a' * 500)
+ with self.open(file_path, "wb", buffering=512) as f:
+ f.write(b"a" * 500)
with self.open(file_path, "rb") as r:
x = r.read()
# buffer not filled - not written
self.assertEqual(0, len(x))
- f.write(b'a' * 400)
+ f.write(b"a" * 400)
with self.open(file_path, "rb") as r:
x = r.read()
# buffer exceeded, but new buffer (400) not - previous written
self.assertEqual(500, len(x))
- f.write(b'a' * 100)
+ f.write(b"a" * 100)
with self.open(file_path, "rb") as r:
x = r.read()
# buffer not full (500) not written
self.assertEqual(500, len(x))
- f.write(b'a' * 100)
+ f.write(b"a" * 100)
with self.open(file_path, "rb") as r:
x = r.read()
# buffer exceeded (600) -> write previous
# new buffer not full (100) - not written
self.assertEqual(1000, len(x))
- f.write(b'a' * 600)
+ f.write(b"a" * 600)
with self.open(file_path, "rb") as r:
x = r.read()
# new buffer exceeded (600) -> all written
@@ -1092,23 +1191,23 @@ class BufferingModeTest(FakeFileOpenTestBase):
def test_writing_text_with_line_buffer(self):
file_path = self.make_path("buffertest.bin")
- with self.open(file_path, 'w', buffering=1) as f:
- f.write('test' * 100)
+ with self.open(file_path, "w", buffering=1) as f:
+ f.write("test" * 100)
with self.open(file_path, "r") as r:
x = r.read()
# no new line - not written
self.assertEqual(0, len(x))
- f.write('\ntest')
+ f.write("\ntest")
with self.open(file_path, "r") as r:
x = r.read()
# new line - buffer written
self.assertEqual(405, len(x))
- f.write('test' * 10)
+ f.write("test" * 10)
with self.open(file_path, "r") as r:
x = r.read()
# buffer not filled - not written
self.assertEqual(405, len(x))
- f.write('\ntest')
+ f.write("\ntest")
with self.open(file_path, "r") as r:
x = r.read()
# new line - buffer written
@@ -1116,23 +1215,23 @@ class BufferingModeTest(FakeFileOpenTestBase):
def test_writing_large_text_with_line_buffer(self):
file_path = self.make_path("buffertest.bin")
- with self.open(file_path, 'w', buffering=1) as f:
- f.write('test' * 4000)
+ with self.open(file_path, "w", buffering=1) as f:
+ f.write("test" * 4000)
with self.open(file_path, "r") as r:
x = r.read()
# buffer larger than default - written
self.assertEqual(16000, len(x))
- f.write('test')
+ f.write("test")
with self.open(file_path, "r") as r:
x = r.read()
# buffer not filled - not written
self.assertEqual(16000, len(x))
- f.write('\ntest')
+ f.write("\ntest")
with self.open(file_path, "r") as r:
x = r.read()
# new line - buffer written
self.assertEqual(16009, len(x))
- f.write('\ntest')
+ f.write("\ntest")
with self.open(file_path, "r") as r:
x = r.read()
# another new line - buffer written
@@ -1140,46 +1239,46 @@ class BufferingModeTest(FakeFileOpenTestBase):
def test_writing_text_with_default_buffer(self):
file_path = self.make_path("buffertest.txt")
- with self.open(file_path, 'w') as f:
- f.write('test' * 5)
+ with self.open(file_path, "w") as f:
+ f.write("test" * 5)
with self.open(file_path, "r") as r:
x = r.read()
# buffer not filled - not written
self.assertEqual(0, len(x))
- f.write('\ntest')
+ f.write("\ntest")
with self.open(file_path, "r") as r:
x = r.read()
# buffer exceeded, but new buffer (400) not - previous written
self.assertEqual(0, len(x))
- f.write('test' * 10)
+ f.write("test" * 10)
with self.open(file_path, "r") as r:
x = r.read()
# buffer not filled - not written
self.assertEqual(0, len(x))
- f.write('\ntest')
+ f.write("\ntest")
with self.open(file_path, "r") as r:
x = r.read()
self.assertEqual(0, len(x))
def test_writing_text_with_specific_buffer(self):
file_path = self.make_path("buffertest.txt")
- with self.open(file_path, 'w', buffering=2) as f:
- f.write('a' * 8000)
+ with self.open(file_path, "w", buffering=2) as f:
+ f.write("a" * 8000)
with self.open(file_path, "r") as r:
x = r.read()
# buffer not filled - not written
self.assertEqual(0, len(x))
- f.write('test')
+ f.write("test")
with self.open(file_path, "r") as r:
x = r.read()
# buffer exceeded, but new buffer (400) not - previous written
self.assertEqual(0, len(x))
- f.write('test')
+ f.write("test")
with self.open(file_path, "r") as r:
x = r.read()
# buffer not filled - not written
self.assertEqual(0, len(x))
- f.write('test')
+ f.write("test")
with self.open(file_path, "r") as r:
x = r.read()
self.assertEqual(0, len(x))
@@ -1189,31 +1288,31 @@ class BufferingModeTest(FakeFileOpenTestBase):
def test_append_with_specific_buffer(self):
file_path = self.make_path("buffertest.bin")
- with self.open(file_path, 'wb', buffering=512) as f:
- f.write(b'a' * 500)
- with self.open(file_path, 'ab', buffering=512) as f:
- f.write(b'a' * 500)
+ with self.open(file_path, "wb", buffering=512) as f:
+ f.write(b"a" * 500)
+ with self.open(file_path, "ab", buffering=512) as f:
+ f.write(b"a" * 500)
with self.open(file_path, "rb") as r:
x = r.read()
# buffer not filled - not written
self.assertEqual(500, len(x))
- f.write(b'a' * 400)
+ f.write(b"a" * 400)
with self.open(file_path, "rb") as r:
x = r.read()
# buffer exceeded, but new buffer (400) not - previous written
self.assertEqual(1000, len(x))
- f.write(b'a' * 100)
+ f.write(b"a" * 100)
with self.open(file_path, "rb") as r:
x = r.read()
# buffer not full (500) not written
self.assertEqual(1000, len(x))
- f.write(b'a' * 100)
+ f.write(b"a" * 100)
with self.open(file_path, "rb") as r:
x = r.read()
# buffer exceeded (600) -> write previous
# new buffer not full (100) - not written
self.assertEqual(1500, len(x))
- f.write(b'a' * 600)
+ f.write(b"a" * 600)
with self.open(file_path, "rb") as r:
x = r.read()
# new buffer exceeded (600) -> all written
@@ -1224,19 +1323,19 @@ class BufferingModeTest(FakeFileOpenTestBase):
self.skip_real_fs() # cannot set fs size in real fs
self.filesystem.set_disk_usage(100)
self.os.makedirs("foo")
- file_path = self.os.path.join('foo', 'bar.txt')
- with self.open(file_path, 'wb') as f:
- f.write(b'a' * 50)
+ file_path = self.os.path.join("foo", "bar.txt")
+ with self.open(file_path, "wb") as f:
+ f.write(b"a" * 50)
f.flush()
with self.open(file_path, "rb") as r:
x = r.read()
- self.assertTrue(x.startswith(b'a' * 50))
+ self.assertTrue(x.startswith(b"a" * 50))
with self.assertRaises(OSError):
- f.write(b'b' * 200)
+ f.write(b"b" * 200)
f.flush()
with self.open(file_path, "rb") as r:
x = r.read()
- self.assertTrue(x.startswith(b'a' * 50))
+ self.assertTrue(x.startswith(b"a" * 50))
f.truncate(50)
def test_failed_write_does_not_truncate_file(self):
@@ -1244,17 +1343,17 @@ class BufferingModeTest(FakeFileOpenTestBase):
self.skip_real_fs() # cannot set fs size in real fs
self.filesystem.set_disk_usage(100)
self.os.makedirs("foo")
- file_path = self.os.path.join('foo', 'bar.txt')
- with self.open(file_path, 'wb', buffering=0) as f:
- f.write(b'a' * 50)
+ file_path = self.os.path.join("foo", "bar.txt")
+ with self.open(file_path, "wb", buffering=0) as f:
+ f.write(b"a" * 50)
with self.open(file_path, "rb") as r:
x = r.read()
- self.assertEqual(b'a' * 50, x)
+ self.assertEqual(b"a" * 50, x)
with self.assertRaises(OSError):
- f.write(b'b' * 200)
+ f.write(b"b" * 200)
with self.open(file_path, "rb") as r:
x = r.read()
- self.assertEqual(b'a' * 50, x)
+ self.assertEqual(b"a" * 50, x)
class RealBufferingTest(BufferingModeTest):
@@ -1268,161 +1367,155 @@ class OpenFileWithEncodingTest(FakeFileOpenTestBase):
def setUp(self):
super(OpenFileWithEncodingTest, self).setUp()
- self.file_path = self.make_path('foo')
+ self.file_path = self.make_path("foo")
def test_write_str_read_bytes(self):
- str_contents = u'علي بابا'
- with self.open(self.file_path, 'w', encoding='arabic') as f:
+ str_contents = "علي بابا"
+ with self.open(self.file_path, "w", encoding="arabic") as f:
f.write(str_contents)
- with self.open(self.file_path, 'rb') as f:
+ with self.open(self.file_path, "rb") as f:
contents = f.read()
- self.assertEqual(str_contents, contents.decode('arabic'))
+ self.assertEqual(str_contents, contents.decode("arabic"))
def test_write_str_error_modes(self):
- str_contents = u'علي بابا'
- with self.open(self.file_path, 'w', encoding='cyrillic') as f:
+ str_contents = "علي بابا"
+ with self.open(self.file_path, "w", encoding="cyrillic") as f:
with self.assertRaises(UnicodeEncodeError):
f.write(str_contents)
- with self.open(self.file_path, 'w', encoding='ascii',
- errors='xmlcharrefreplace') as f:
+ with self.open(
+ self.file_path, "w", encoding="ascii", errors="xmlcharrefreplace"
+ ) as f:
f.write(str_contents)
- with self.open(self.file_path, 'r', encoding='ascii') as f:
+ with self.open(self.file_path, "r", encoding="ascii") as f:
contents = f.read()
- self.assertEqual('&#1593;&#1604;&#1610; &#1576;&#1575;&#1576;&#1575;',
- contents)
+ self.assertEqual("&#1593;&#1604;&#1610; &#1576;&#1575;&#1576;&#1575;", contents)
- with self.open(self.file_path, 'w', encoding='ascii',
- errors='namereplace') as f:
+ with self.open(
+ self.file_path, "w", encoding="ascii", errors="namereplace"
+ ) as f:
f.write(str_contents)
- with self.open(self.file_path, 'r', encoding='ascii') as f:
+ with self.open(self.file_path, "r", encoding="ascii") as f:
contents = f.read()
self.assertEqual(
- r'\N{ARABIC LETTER AIN}\N{ARABIC LETTER LAM}\N'
- r'{ARABIC LETTER YEH} \N{ARABIC LETTER BEH}\N'
- r'{ARABIC LETTER ALEF}\N{ARABIC LETTER BEH}'
- r'\N{ARABIC LETTER ALEF}', contents)
+ r"\N{ARABIC LETTER AIN}\N{ARABIC LETTER LAM}\N"
+ r"{ARABIC LETTER YEH} \N{ARABIC LETTER BEH}\N"
+ r"{ARABIC LETTER ALEF}\N{ARABIC LETTER BEH}"
+ r"\N{ARABIC LETTER ALEF}",
+ contents,
+ )
def test_read_str_error_modes(self):
- str_contents = u'علي بابا'
- with self.open(self.file_path, 'w', encoding='arabic') as f:
+ str_contents = "علي بابا"
+ with self.open(self.file_path, "w", encoding="arabic") as f:
f.write(str_contents)
# default strict encoding
- with self.open(self.file_path, encoding='ascii') as f:
+ with self.open(self.file_path, encoding="ascii") as f:
with self.assertRaises(UnicodeDecodeError):
f.read()
- with self.open(self.file_path, encoding='ascii',
- errors='replace') as f:
+ with self.open(self.file_path, encoding="ascii", errors="replace") as f:
contents = f.read()
self.assertNotEqual(str_contents, contents)
- with self.open(self.file_path, encoding='ascii',
- errors='backslashreplace') as f:
+ with self.open(
+ self.file_path, encoding="ascii", errors="backslashreplace"
+ ) as f:
contents = f.read()
- self.assertEqual(r'\xd9\xe4\xea \xc8\xc7\xc8\xc7', contents)
+ self.assertEqual(r"\xd9\xe4\xea \xc8\xc7\xc8\xc7", contents)
def test_write_and_read_str(self):
- str_contents = u'علي بابا'
- with self.open(self.file_path, 'w', encoding='arabic') as f:
+ str_contents = "علي بابا"
+ with self.open(self.file_path, "w", encoding="arabic") as f:
f.write(str_contents)
- with self.open(self.file_path, 'r', encoding='arabic') as f:
+ with self.open(self.file_path, "r", encoding="arabic") as f:
contents = f.read()
self.assertEqual(str_contents, contents)
def test_create_file_with_append(self):
contents = [
- u'Allons enfants de la Patrie,'
- u'Le jour de gloire est arrivé!',
- u'Contre nous de la tyrannie,',
- u'L’étendard sanglant est levé.',
+ "Allons enfants de la Patrie," "Le jour de gloire est arrivé!",
+ "Contre nous de la tyrannie,",
+ "L’étendard sanglant est levé.",
]
- with self.open(self.file_path, 'a', encoding='utf-8') as fake_file:
+ with self.open(self.file_path, "a", encoding="utf-8") as fake_file:
for line in contents:
- fake_file.write(line + '\n')
- with self.open(self.file_path, encoding='utf-8') as fake_file:
+ fake_file.write(line + "\n")
+ with self.open(self.file_path, encoding="utf-8") as fake_file:
result = [line.rstrip() for line in fake_file]
self.assertEqual(contents, result)
def test_append_existing_file(self):
contents = [
- u'Оригинальное содержание'
- u'Дополнительное содержание',
+ "Оригинальное содержание" "Дополнительное содержание",
]
- self.create_file(self.file_path, contents=contents[0],
- encoding='cyrillic')
- with self.open(self.file_path, 'a', encoding='cyrillic') as fake_file:
+ self.create_file(self.file_path, contents=contents[0], encoding="cyrillic")
+ with self.open(self.file_path, "a", encoding="cyrillic") as fake_file:
for line in contents[1:]:
- fake_file.write(line + '\n')
- with self.open(self.file_path, encoding='cyrillic') as fake_file:
+ fake_file.write(line + "\n")
+ with self.open(self.file_path, encoding="cyrillic") as fake_file:
result = [line.rstrip() for line in fake_file]
self.assertEqual(contents, result)
def test_open_with_wplus(self):
- self.create_file(self.file_path,
- contents=u'старое содержание',
- encoding='cyrillic')
- with self.open(self.file_path, 'r', encoding='cyrillic') as fake_file:
- self.assertEqual(u'старое содержание', fake_file.read())
-
- with self.open(self.file_path, 'w+', encoding='cyrillic') as fake_file:
- fake_file.write(u'новое содержание')
+ self.create_file(
+ self.file_path, contents="старое содержание", encoding="cyrillic"
+ )
+ with self.open(self.file_path, "r", encoding="cyrillic") as fake_file:
+ self.assertEqual("старое содержание", fake_file.read())
+
+ with self.open(self.file_path, "w+", encoding="cyrillic") as fake_file:
+ fake_file.write("новое содержание")
fake_file.seek(0)
- self.assertTrue(u'новое содержание', fake_file.read())
+ self.assertTrue("новое содержание", fake_file.read())
def test_open_with_append_flag(self):
- contents = [
- u'Калинка,\n',
- u'калинка,\n',
- u'калинка моя,\n'
- ]
- additional_contents = [
- u'В саду ягода-малинка,\n',
- u'малинка моя.\n'
- ]
- self.create_file(self.file_path, contents=''.join(contents),
- encoding='cyrillic')
- with self.open(self.file_path, 'a', encoding='cyrillic') as fake_file:
+ contents = ["Калинка,\n", "калинка,\n", "калинка моя,\n"]
+ additional_contents = ["В саду ягода-малинка,\n", "малинка моя.\n"]
+ self.create_file(
+ self.file_path, contents="".join(contents), encoding="cyrillic"
+ )
+ with self.open(self.file_path, "a", encoding="cyrillic") as fake_file:
with self.assertRaises(io.UnsupportedOperation):
fake_file.read(0)
with self.assertRaises(io.UnsupportedOperation):
fake_file.readline()
- self.assertEqual(len(''.join(contents)), fake_file.tell())
+ self.assertEqual(len("".join(contents)), fake_file.tell())
fake_file.seek(0)
self.assertEqual(0, fake_file.tell())
fake_file.writelines(additional_contents)
- with self.open(self.file_path, encoding='cyrillic') as fake_file:
- self.assertEqual(contents + additional_contents,
- fake_file.readlines())
+ with self.open(self.file_path, encoding="cyrillic") as fake_file:
+ self.assertEqual(contents + additional_contents, fake_file.readlines())
def test_append_with_aplus(self):
- self.create_file(self.file_path,
- contents=u'старое содержание',
- encoding='cyrillic')
- fake_file = self.open(self.file_path, 'r', encoding='cyrillic')
+ self.create_file(
+ self.file_path, contents="старое содержание", encoding="cyrillic"
+ )
+ fake_file = self.open(self.file_path, "r", encoding="cyrillic")
fake_file.close()
- with self.open(self.file_path, 'a+', encoding='cyrillic') as fake_file:
+ with self.open(self.file_path, "a+", encoding="cyrillic") as fake_file:
self.assertEqual(17, fake_file.tell())
- fake_file.write(u'новое содержание')
+ fake_file.write("новое содержание")
self.assertEqual(33, fake_file.tell())
fake_file.seek(0)
- self.assertEqual(u'старое содержаниеновое содержание',
- fake_file.read())
+ self.assertEqual("старое содержаниеновое содержание", fake_file.read())
def test_read_with_rplus(self):
- self.create_file(self.file_path,
- contents=u'старое содержание здесь',
- encoding='cyrillic')
- fake_file = self.open(self.file_path, 'r', encoding='cyrillic')
+ self.create_file(
+ self.file_path,
+ contents="старое содержание здесь",
+ encoding="cyrillic",
+ )
+ fake_file = self.open(self.file_path, "r", encoding="cyrillic")
fake_file.close()
- with self.open(self.file_path, 'r+', encoding='cyrillic') as fake_file:
- self.assertEqual(u'старое содержание здесь', fake_file.read())
+ with self.open(self.file_path, "r+", encoding="cyrillic") as fake_file:
+ self.assertEqual("старое содержание здесь", fake_file.read())
fake_file.seek(0)
- fake_file.write(u'новое содержание')
+ fake_file.write("новое содержание")
fake_file.seek(0)
- self.assertEqual(u'новое содержание здесь', fake_file.read())
+ self.assertEqual("новое содержание здесь", fake_file.read())
class OpenRealFileWithEncodingTest(OpenFileWithEncodingTest):
@@ -1435,107 +1528,113 @@ class FakeFileOpenLineEndingTest(FakeFileOpenTestBase):
super(FakeFileOpenLineEndingTest, self).setUp()
def test_read_default_newline_mode(self):
- file_path = self.make_path('some_file')
- for contents in (b'1\n2', b'1\r\n2', b'1\r2'):
+ file_path = self.make_path("some_file")
+ for contents in (b"1\n2", b"1\r\n2", b"1\r2"):
self.create_file(file_path, contents=contents)
- with self.open(file_path, mode='r') as f:
- self.assertEqual(['1\n', '2'], f.readlines())
- with self.open(file_path, mode='r') as f:
- self.assertEqual('1\n2', f.read())
- with self.open(file_path, mode='rb') as f:
+ with self.open(file_path, mode="r") as f:
+ self.assertEqual(["1\n", "2"], f.readlines())
+ with self.open(file_path, mode="r") as f:
+ self.assertEqual("1\n2", f.read())
+ with self.open(file_path, mode="rb") as f:
self.assertEqual(contents, f.read())
def test_write_universal_newline_mode(self):
- file_path = self.make_path('some_file')
- with self.open(file_path, 'w') as f:
- f.write('1\n2')
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(b'1' + self.os.linesep.encode() + b'2',
- f.read())
-
- with self.open(file_path, 'w') as f:
- f.write('1\r\n2')
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(b'1\r' + self.os.linesep.encode() + b'2',
- f.read())
+ file_path = self.make_path("some_file")
+ with self.open(file_path, "w") as f:
+ f.write("1\n2")
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual(b"1" + self.os.linesep.encode() + b"2", f.read())
+
+ with self.open(file_path, "w") as f:
+ f.write("1\r\n2")
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual(b"1\r" + self.os.linesep.encode() + b"2", f.read())
def test_read_with_newline_arg(self):
- file_path = self.make_path('some_file')
- file_contents = b'1\r\n2\n3\r4'
+ file_path = self.make_path("some_file")
+ file_contents = b"1\r\n2\n3\r4"
self.create_file(file_path, contents=file_contents)
- with self.open(file_path, mode='r', newline='') as f:
- self.assertEqual('1\r\n2\n3\r4', f.read())
- with self.open(file_path, mode='r', newline='\r') as f:
- self.assertEqual('1\r\n2\n3\r4', f.read())
- with self.open(file_path, mode='r', newline='\n') as f:
- self.assertEqual('1\r\n2\n3\r4', f.read())
- with self.open(file_path, mode='r', newline='\r\n') as f:
- self.assertEqual('1\r\n2\n3\r4', f.read())
+ with self.open(file_path, mode="r", newline="") as f:
+ self.assertEqual("1\r\n2\n3\r4", f.read())
+ with self.open(file_path, mode="r", newline="\r") as f:
+ self.assertEqual("1\r\n2\n3\r4", f.read())
+ with self.open(file_path, mode="r", newline="\n") as f:
+ self.assertEqual("1\r\n2\n3\r4", f.read())
+ with self.open(file_path, mode="r", newline="\r\n") as f:
+ self.assertEqual("1\r\n2\n3\r4", f.read())
def test_readlines_with_newline_arg(self):
- file_path = self.make_path('some_file')
- file_contents = b'1\r\n2\n3\r4'
+ file_path = self.make_path("some_file")
+ file_contents = b"1\r\n2\n3\r4"
self.create_file(file_path, contents=file_contents)
- with self.open(file_path, mode='r', newline='') as f:
- self.assertEqual(['1\r\n', '2\n', '3\r', '4'],
- f.readlines())
- with self.open(file_path, mode='r', newline='\r') as f:
- self.assertEqual(['1\r', '\n2\n3\r', '4'], f.readlines())
- with self.open(file_path, mode='r', newline='\n') as f:
- self.assertEqual(['1\r\n', '2\n', '3\r4'], f.readlines())
- with self.open(file_path, mode='r', newline='\r\n') as f:
- self.assertEqual(['1\r\n', '2\n3\r4'], f.readlines())
-
+ with self.open(file_path, mode="r", newline="") as f:
+ self.assertEqual(["1\r\n", "2\n", "3\r", "4"], f.readlines())
+ with self.open(file_path, mode="r", newline="\r") as f:
+ self.assertEqual(["1\r", "\n2\n3\r", "4"], f.readlines())
+ with self.open(file_path, mode="r", newline="\n") as f:
+ self.assertEqual(["1\r\n", "2\n", "3\r4"], f.readlines())
+ with self.open(file_path, mode="r", newline="\r\n") as f:
+ self.assertEqual(["1\r\n", "2\n3\r4"], f.readlines())
+
+ @unittest.skipIf(sys.version_info >= (3, 10), "U flag no longer supported")
def test_read_with_ignored_universal_newlines_flag(self):
- file_path = self.make_path('some_file')
- file_contents = b'1\r\n2\n3\r4'
+ file_path = self.make_path("some_file")
+ file_contents = b"1\r\n2\n3\r4"
self.create_file(file_path, contents=file_contents)
- with self.open(file_path, mode='r', newline='\r') as f:
- self.assertEqual('1\r\n2\n3\r4', f.read())
- with self.open(file_path, mode='r', newline='\r') as f:
- self.assertEqual('1\r\n2\n3\r4', f.read())
- with self.open(file_path, mode='U', newline='\r') as f:
- self.assertEqual('1\r\n2\n3\r4', f.read())
+ with self.open(file_path, mode="r", newline="\r") as f:
+ self.assertEqual("1\r\n2\n3\r4", f.read())
+ with self.open(file_path, mode="r", newline="\r") as f:
+ self.assertEqual("1\r\n2\n3\r4", f.read())
+ with self.open(file_path, mode="U", newline="\r") as f:
+ self.assertEqual("1\r\n2\n3\r4", f.read())
+
+ @unittest.skipIf(sys.version_info < (3, 11), "U flag still supported")
+ def test_universal_newlines_flag_not_supported(self):
+ file_path = self.make_path("some_file")
+ file_contents = b"1\r\n2\n3\r4"
+ self.create_file(file_path, contents=file_contents)
+ with self.assertRaises(ValueError):
+ self.open(file_path, mode="U", newline="\r")
def test_write_with_newline_arg(self):
- file_path = self.make_path('some_file')
- with self.open(file_path, 'w', newline='') as f:
- f.write('1\r\n2\n3\r4')
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(b'1\r\n2\n3\r4', f.read())
-
- with self.open(file_path, 'w', newline='\n') as f:
- f.write('1\r\n2\n3\r4')
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(b'1\r\n2\n3\r4', f.read())
-
- with self.open(file_path, 'w', newline='\r\n') as f:
- f.write('1\r\n2\n3\r4')
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(b'1\r\r\n2\r\n3\r4', f.read())
-
- with self.open(file_path, 'w', newline='\r') as f:
- f.write('1\r\n2\n3\r4')
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(b'1\r\r2\r3\r4', f.read())
+ file_path = self.make_path("some_file")
+ with self.open(file_path, "w", newline="") as f:
+ f.write("1\r\n2\n3\r4")
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual(b"1\r\n2\n3\r4", f.read())
+
+ with self.open(file_path, "w", newline="\n") as f:
+ f.write("1\r\n2\n3\r4")
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual(b"1\r\n2\n3\r4", f.read())
+
+ with self.open(file_path, "w", newline="\r\n") as f:
+ f.write("1\r\n2\n3\r4")
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual(b"1\r\r\n2\r\n3\r4", f.read())
+
+ with self.open(file_path, "w", newline="\r") as f:
+ f.write("1\r\n2\n3\r4")
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual(b"1\r\r2\r3\r4", f.read())
def test_binary_readline(self):
- file_path = self.make_path('some_file')
- file_contents = b'\x80\n\x80\r\x80\r\n\x80'
+ file_path = self.make_path("some_file")
+ file_contents = b"\x80\n\x80\r\x80\r\n\x80"
def chunk_line():
px = 0
while px < len(file_contents):
- ix = file_contents.find(b'\n', px)
+ ix = file_contents.find(b"\n", px)
if ix == -1:
yield file_contents[px:]
return
- yield file_contents[px:ix + 1]
+ yield file_contents[px : ix + 1]
px = ix + 1
chunked_contents = list(chunk_line())
self.create_file(file_path, contents=file_contents)
- with self.open(file_path, mode='rb') as f:
+ with self.open(file_path, mode="rb") as f:
self.assertEqual(chunked_contents, list(f))
@@ -1549,124 +1648,105 @@ class FakeFileOpenLineEndingWithEncodingTest(FakeFileOpenTestBase):
super(FakeFileOpenLineEndingWithEncodingTest, self).setUp()
def test_read_standard_newline_mode(self):
- file_path = self.make_path('some_file')
- for contents in (u'раз\nдва', u'раз\r\nдва', u'раз\rдва'):
- self.create_file(file_path, contents=contents, encoding='cyrillic')
- with self.open(file_path, mode='r',
- encoding='cyrillic') as fake_file:
- self.assertEqual([u'раз\n', u'два'], fake_file.readlines())
- with self.open(file_path, mode='r',
- encoding='cyrillic') as fake_file:
- self.assertEqual(u'раз\nдва', fake_file.read())
+ file_path = self.make_path("some_file")
+ for contents in ("раз\nдва", "раз\r\nдва", "раз\rдва"):
+ self.create_file(file_path, contents=contents, encoding="cyrillic")
+ with self.open(file_path, mode="r", encoding="cyrillic") as fake_file:
+ self.assertEqual(["раз\n", "два"], fake_file.readlines())
+ with self.open(file_path, mode="r", encoding="cyrillic") as fake_file:
+ self.assertEqual("раз\nдва", fake_file.read())
def test_write_universal_newline_mode(self):
- file_path = self.make_path('some_file')
- with self.open(file_path, 'w', encoding='cyrillic') as f:
- f.write(u'раз\nдва')
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(u'раз'.encode('cyrillic') +
- self.os.linesep.encode()
- + u'два'.encode('cyrillic'), f.read())
-
- with self.open(file_path, 'w', encoding='cyrillic') as f:
- f.write(u'раз\r\nдва')
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(u'раз\r'.encode('cyrillic') +
- self.os.linesep.encode() +
- u'два'.encode('cyrillic'), f.read())
+ file_path = self.make_path("some_file")
+ with self.open(file_path, "w", encoding="cyrillic") as f:
+ f.write("раз\nдва")
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual(
+ "раз".encode("cyrillic")
+ + self.os.linesep.encode()
+ + "два".encode("cyrillic"),
+ f.read(),
+ )
+
+ with self.open(file_path, "w", encoding="cyrillic") as f:
+ f.write("раз\r\nдва")
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual(
+ "раз\r".encode("cyrillic")
+ + self.os.linesep.encode()
+ + "два".encode("cyrillic"),
+ f.read(),
+ )
def test_read_with_newline_arg(self):
- file_path = self.make_path('some_file')
- file_contents = u'раз\r\nдва\nтри\rчетыре'
- self.create_file(file_path, contents=file_contents,
- encoding='cyrillic')
- with self.open(file_path, mode='r', newline='',
- encoding='cyrillic') as f:
- self.assertEqual(u'раз\r\nдва\nтри\rчетыре', f.read())
- with self.open(file_path, mode='r', newline='\r',
- encoding='cyrillic') as f:
- self.assertEqual(u'раз\r\nдва\nтри\rчетыре', f.read())
- with self.open(file_path, mode='r', newline='\n',
- encoding='cyrillic') as f:
- self.assertEqual(u'раз\r\nдва\nтри\rчетыре', f.read())
- with self.open(file_path, mode='r', newline='\r\n',
- encoding='cyrillic') as f:
- self.assertEqual(u'раз\r\nдва\nтри\rчетыре', f.read())
+ file_path = self.make_path("some_file")
+ file_contents = "раз\r\nдва\nтри\rчетыре"
+ self.create_file(file_path, contents=file_contents, encoding="cyrillic")
+ with self.open(file_path, mode="r", newline="", encoding="cyrillic") as f:
+ self.assertEqual("раз\r\nдва\nтри\rчетыре", f.read())
+ with self.open(file_path, mode="r", newline="\r", encoding="cyrillic") as f:
+ self.assertEqual("раз\r\nдва\nтри\rчетыре", f.read())
+ with self.open(file_path, mode="r", newline="\n", encoding="cyrillic") as f:
+ self.assertEqual("раз\r\nдва\nтри\rчетыре", f.read())
+ with self.open(file_path, mode="r", newline="\r\n", encoding="cyrillic") as f:
+ self.assertEqual("раз\r\nдва\nтри\rчетыре", f.read())
def test_readlines_with_newline_arg(self):
- file_path = self.make_path('some_file')
- file_contents = u'раз\r\nдва\nтри\rчетыре'
- self.create_file(file_path, contents=file_contents,
- encoding='cyrillic')
- with self.open(file_path, mode='r', newline='',
- encoding='cyrillic') as f:
- self.assertEqual([u'раз\r\n', u'два\n', u'три\r', u'четыре'],
- f.readlines())
- with self.open(file_path, mode='r', newline='\r',
- encoding='cyrillic') as f:
- self.assertEqual([u'раз\r', u'\nдва\nтри\r', u'четыре'],
- f.readlines())
- with self.open(file_path, mode='r', newline='\n',
- encoding='cyrillic') as f:
- self.assertEqual([u'раз\r\n', u'два\n', u'три\rчетыре'],
- f.readlines())
- with self.open(file_path, mode='r', newline='\r\n',
- encoding='cyrillic') as f:
- self.assertEqual([u'раз\r\n', u'два\nтри\rчетыре'],
- f.readlines())
+ file_path = self.make_path("some_file")
+ file_contents = "раз\r\nдва\nтри\rчетыре"
+ self.create_file(file_path, contents=file_contents, encoding="cyrillic")
+ with self.open(file_path, mode="r", newline="", encoding="cyrillic") as f:
+ self.assertEqual(["раз\r\n", "два\n", "три\r", "четыре"], f.readlines())
+ with self.open(file_path, mode="r", newline="\r", encoding="cyrillic") as f:
+ self.assertEqual(["раз\r", "\nдва\nтри\r", "четыре"], f.readlines())
+ with self.open(file_path, mode="r", newline="\n", encoding="cyrillic") as f:
+ self.assertEqual(["раз\r\n", "два\n", "три\rчетыре"], f.readlines())
+ with self.open(file_path, mode="r", newline="\r\n", encoding="cyrillic") as f:
+ self.assertEqual(["раз\r\n", "два\nтри\rчетыре"], f.readlines())
def test_write_with_newline_arg(self):
- file_path = self.make_path('some_file')
- with self.open(file_path, 'w', newline='',
- encoding='cyrillic') as f:
- f.write(u'раз\r\nдва\nтри\rчетыре')
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(u'раз\r\nдва\nтри\rчетыре'.encode('cyrillic'),
- f.read())
-
- with self.open(file_path, 'w', newline='\n',
- encoding='cyrillic') as f:
- f.write('раз\r\nдва\nтри\rчетыре')
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(u'раз\r\nдва\nтри\rчетыре'.encode('cyrillic'),
- f.read())
-
- with self.open(file_path, 'w', newline='\r\n',
- encoding='cyrillic') as f:
- f.write('раз\r\nдва\nтри\rчетыре')
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(u'раз\r\r\nдва\r\nтри\rчетыре'.encode('cyrillic'),
- f.read())
-
- with self.open(file_path, 'w', newline='\r',
- encoding='cyrillic') as f:
- f.write('раз\r\nдва\nтри\rчетыре')
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(u'раз\r\rдва\rтри\rчетыре'.encode('cyrillic'),
- f.read())
-
-
-class RealFileOpenLineEndingWithEncodingTest(
- FakeFileOpenLineEndingWithEncodingTest):
+ file_path = self.make_path("some_file")
+ with self.open(file_path, "w", newline="", encoding="cyrillic") as f:
+ f.write("раз\r\nдва\nтри\rчетыре")
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual("раз\r\nдва\nтри\rчетыре".encode("cyrillic"), f.read())
+
+ with self.open(file_path, "w", newline="\n", encoding="cyrillic") as f:
+ f.write("раз\r\nдва\nтри\rчетыре")
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual("раз\r\nдва\nтри\rчетыре".encode("cyrillic"), f.read())
+
+ with self.open(file_path, "w", newline="\r\n", encoding="cyrillic") as f:
+ f.write("раз\r\nдва\nтри\rчетыре")
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual("раз\r\r\nдва\r\nтри\rчетыре".encode("cyrillic"), f.read())
+
+ with self.open(file_path, "w", newline="\r", encoding="cyrillic") as f:
+ f.write("раз\r\nдва\nтри\rчетыре")
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual("раз\r\rдва\rтри\rчетыре".encode("cyrillic"), f.read())
+
+
+class RealFileOpenLineEndingWithEncodingTest(FakeFileOpenLineEndingWithEncodingTest):
def use_real_fs(self):
return True
class OpenWithFileDescriptorTest(FakeFileOpenTestBase):
def test_open_with_file_descriptor(self):
- file_path = self.make_path('this', 'file')
+ file_path = self.make_path("this", "file")
self.create_file(file_path)
fd = self.os.open(file_path, os.O_CREAT)
- self.assertEqual(fd, self.open(fd, 'r').fileno())
+ self.assertEqual(fd, self.open(fd, "r").fileno())
def test_closefd_with_file_descriptor(self):
- file_path = self.make_path('this', 'file')
+ file_path = self.make_path("this", "file")
self.create_file(file_path)
fd = self.os.open(file_path, os.O_CREAT)
- fh = self.open(fd, 'r', closefd=False)
+ fh = self.open(fd, "r", closefd=False)
fh.close()
self.assertIsNotNone(self.filesystem.open_files[fd])
- fh = self.open(fd, 'r', closefd=True)
+ fh = self.open(fd, "r", closefd=True)
fh.close()
self.assertIsNone(self.filesystem.open_files[fd])
@@ -1679,7 +1759,7 @@ class OpenWithRealFileDescriptorTest(FakeFileOpenTestBase):
class OpenWithFlagsTestBase(FakeFileOpenTestBase):
def setUp(self):
super(OpenWithFlagsTestBase, self).setUp()
- self.file_path = self.make_path('some_file')
+ self.file_path = self.make_path("some_file")
self.file_contents = None
def open_file(self, mode):
@@ -1690,41 +1770,42 @@ class OpenWithFlagsTestBase(FakeFileOpenTestBase):
fake_file.seek(0, 2)
return fake_file
- def write_and_reopen_file(self, fake_file, mode='r', encoding=None):
+ def write_and_reopen_file(self, fake_file, mode="r", encoding=None):
fake_file.write(self.file_contents)
fake_file.close()
- args = {'mode': mode}
+ args = {"mode": mode}
if encoding:
- args['encoding'] = encoding
+ args["encoding"] = encoding
return self.open(self.file_path, **args)
class OpenWithBinaryFlagsTest(OpenWithFlagsTestBase):
def setUp(self):
super(OpenWithBinaryFlagsTest, self).setUp()
- self.file_contents = b'real binary contents: \x1f\x8b'
+ self.file_contents = b"real binary contents: \x1f\x8b"
self.create_file(self.file_path, contents=self.file_contents)
def test_read_binary(self):
- with self.open_file('rb') as fake_file:
+ with self.open_file("rb") as fake_file:
self.assertEqual(self.file_contents, fake_file.read())
def test_write_binary(self):
- with self.open_file_and_seek('wb') as f:
+ with self.open_file_and_seek("wb") as f:
self.assertEqual(0, f.tell())
- with self.write_and_reopen_file(f, mode='rb') as f1:
+ with self.write_and_reopen_file(f, mode="rb") as f1:
self.assertEqual(self.file_contents, f1.read())
# Attempt to reopen the file in text mode
- with self.open_file('wb') as f2:
- with self.write_and_reopen_file(f2, mode='r',
- encoding='ascii') as f3:
+ with self.open_file("wb") as f2:
+ with self.write_and_reopen_file(
+ f2, mode="r", encoding="ascii"
+ ) as f3:
with self.assertRaises(UnicodeDecodeError):
f3.read()
def test_write_and_read_binary(self):
- with self.open_file_and_seek('w+b') as f:
+ with self.open_file_and_seek("w+b") as f:
self.assertEqual(0, f.tell())
- with self.write_and_reopen_file(f, mode='rb') as f1:
+ with self.write_and_reopen_file(f, mode="rb") as f1:
self.assertEqual(self.file_contents, f1.read())
@@ -1739,23 +1820,23 @@ class OpenWithTextModeFlagsTest(OpenWithFlagsTestBase):
self.setUpFileSystem()
def setUpFileSystem(self):
- self.file_path = self.make_path('some_file')
- self.file_contents = b'two\r\nlines'
- self.original_contents = 'two\r\nlines'
- self.converted_contents = 'two\nlines'
+ self.file_path = self.make_path("some_file")
+ self.file_contents = b"two\r\nlines"
+ self.original_contents = "two\r\nlines"
+ self.converted_contents = "two\nlines"
self.create_file(self.file_path, contents=self.file_contents)
def test_read_text(self):
"""Test that text mode flag is ignored"""
self.check_windows_only()
- with self.open_file('r') as f:
+ with self.open_file("r") as f:
self.assertEqual(self.converted_contents, f.read())
- with self.open_file('rt') as f:
+ with self.open_file("rt") as f:
self.assertEqual(self.converted_contents, f.read())
def test_mixed_text_and_binary_flags(self):
with self.assertRaises(ValueError):
- self.open_file_and_seek('w+bt')
+ self.open_file_and_seek("w+bt")
class RealOpenWithTextModeFlagsTest(OpenWithTextModeFlagsTest):
@@ -1766,23 +1847,23 @@ class RealOpenWithTextModeFlagsTest(OpenWithTextModeFlagsTest):
class OpenWithInvalidFlagsTest(FakeFileOpenTestBase):
def test_capital_r(self):
with self.assertRaises(ValueError):
- self.open('some_file', 'R')
+ self.open("some_file", "R")
def test_capital_w(self):
with self.assertRaises(ValueError):
- self.open('some_file', 'W')
+ self.open("some_file", "W")
def test_capital_a(self):
with self.assertRaises(ValueError):
- self.open('some_file', 'A')
+ self.open("some_file", "A")
def test_lower_u(self):
with self.assertRaises(ValueError):
- self.open('some_file', 'u')
+ self.open("some_file", "u")
def test_lower_rw(self):
with self.assertRaises(ValueError):
- self.open('some_file', 'rw')
+ self.open("some_file", "rw")
class OpenWithInvalidFlagsRealFsTest(OpenWithInvalidFlagsTest):
@@ -1792,38 +1873,38 @@ class OpenWithInvalidFlagsRealFsTest(OpenWithInvalidFlagsTest):
class ResolvePathTest(FakeFileOpenTestBase):
def write_to_file(self, file_name):
- with self.open(file_name, 'w') as fh:
- fh.write('x')
+ with self.open(file_name, "w") as fh:
+ fh.write("x")
def test_none_filepath_raises_type_error(self):
with self.assertRaises(TypeError):
- self.open(None, 'w')
+ self.open(None, "w")
def test_empty_filepath_raises_io_error(self):
with self.assertRaises(OSError):
- self.open('', 'w')
+ self.open("", "w")
def test_normal_path(self):
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.write_to_file(file_path)
self.assertTrue(self.os.path.exists(file_path))
def test_link_within_same_directory(self):
self.skip_if_symlink_not_supported()
- final_target = self.make_path('foo', 'baz')
- link_path = self.make_path('foo', 'bar')
- self.create_symlink(link_path, 'baz')
+ final_target = self.make_path("foo", "baz")
+ link_path = self.make_path("foo", "bar")
+ self.create_symlink(link_path, "baz")
self.write_to_file(link_path)
self.assertTrue(self.os.path.exists(final_target))
self.assertEqual(1, self.os.stat(final_target)[stat.ST_SIZE])
def test_link_to_sub_directory(self):
self.skip_if_symlink_not_supported()
- final_target = self.make_path('foo', 'baz', 'bip')
- dir_path = self.make_path('foo', 'baz')
+ final_target = self.make_path("foo", "baz", "bip")
+ dir_path = self.make_path("foo", "baz")
self.create_dir(dir_path)
- link_path = self.make_path('foo', 'bar')
- target_path = self.os.path.join('baz', 'bip')
+ link_path = self.make_path("foo", "bar")
+ target_path = self.os.path.join("baz", "bip")
self.create_symlink(link_path, target_path)
self.write_to_file(link_path)
self.assertTrue(self.os.path.exists(final_target))
@@ -1834,81 +1915,78 @@ class ResolvePathTest(FakeFileOpenTestBase):
def test_link_to_parent_directory(self):
self.skip_if_symlink_not_supported()
- final_target = self.make_path('baz', 'bip')
- self.create_dir(self.make_path('foo'))
- self.create_dir(self.make_path('baz'))
- link_path = self.make_path('foo', 'bar')
- self.create_symlink(link_path, self.os.path.join('..', 'baz'))
- self.write_to_file(self.make_path('foo', 'bar', 'bip'))
+ final_target = self.make_path("baz", "bip")
+ self.create_dir(self.make_path("foo"))
+ self.create_dir(self.make_path("baz"))
+ link_path = self.make_path("foo", "bar")
+ self.create_symlink(link_path, self.os.path.join("..", "baz"))
+ self.write_to_file(self.make_path("foo", "bar", "bip"))
self.assertTrue(self.os.path.exists(final_target))
self.assertEqual(1, self.os.stat(final_target)[stat.ST_SIZE])
self.assertTrue(self.os.path.exists(link_path))
def test_link_to_absolute_path(self):
self.skip_if_symlink_not_supported()
- final_target = self.make_path('foo', 'baz', 'bip')
- self.create_dir(self.make_path('foo', 'baz'))
- link_path = self.make_path('foo', 'bar')
+ final_target = self.make_path("foo", "baz", "bip")
+ self.create_dir(self.make_path("foo", "baz"))
+ link_path = self.make_path("foo", "bar")
self.create_symlink(link_path, final_target)
self.write_to_file(link_path)
self.assertTrue(self.os.path.exists(final_target))
def test_relative_links_work_after_chdir(self):
self.skip_if_symlink_not_supported()
- final_target = self.make_path('foo', 'baz', 'bip')
- self.create_dir(self.make_path('foo', 'baz'))
- link_path = self.make_path('foo', 'bar')
- self.create_symlink(link_path, self.os.path.join('.', 'baz', 'bip'))
+ final_target = self.make_path("foo", "baz", "bip")
+ self.create_dir(self.make_path("foo", "baz"))
+ link_path = self.make_path("foo", "bar")
+ self.create_symlink(link_path, self.os.path.join(".", "baz", "bip"))
if not self.is_windows:
- self.assert_equal_paths(
- final_target, self.os.path.realpath(link_path))
+ self.assert_equal_paths(final_target, self.os.path.realpath(link_path))
self.assertTrue(self.os.path.islink(link_path))
- self.os.chdir(self.make_path('foo'))
- self.assert_equal_paths(self.make_path('foo'), self.os.getcwd())
- self.assertTrue(self.os.path.islink('bar'))
+ self.os.chdir(self.make_path("foo"))
+ self.assert_equal_paths(self.make_path("foo"), self.os.getcwd())
+ self.assertTrue(self.os.path.islink("bar"))
if not self.is_windows:
- self.assert_equal_paths(final_target, self.os.path.realpath('bar'))
+ self.assert_equal_paths(final_target, self.os.path.realpath("bar"))
self.write_to_file(link_path)
self.assertTrue(self.os.path.exists(final_target))
def test_absolute_links_work_after_chdir(self):
self.skip_if_symlink_not_supported()
- final_target = self.make_path('foo', 'baz', 'bip')
- self.create_dir(self.make_path('foo', 'baz'))
- link_path = self.make_path('foo', 'bar')
+ final_target = self.make_path("foo", "baz", "bip")
+ self.create_dir(self.make_path("foo", "baz"))
+ link_path = self.make_path("foo", "bar")
self.create_symlink(link_path, final_target)
if not self.is_windows:
- self.assert_equal_paths(
- final_target, self.os.path.realpath(link_path))
+ self.assert_equal_paths(final_target, self.os.path.realpath(link_path))
self.assertTrue(self.os.path.islink(link_path))
- self.os.chdir(self.make_path('foo'))
- self.assert_equal_paths(self.make_path('foo'), self.os.getcwd())
- self.assertTrue(self.os.path.islink('bar'))
+ self.os.chdir(self.make_path("foo"))
+ self.assert_equal_paths(self.make_path("foo"), self.os.getcwd())
+ self.assertTrue(self.os.path.islink("bar"))
if not self.is_windows:
- self.assert_equal_paths(final_target, self.os.path.realpath('bar'))
+ self.assert_equal_paths(final_target, self.os.path.realpath("bar"))
self.write_to_file(link_path)
self.assertTrue(self.os.path.exists(final_target))
def test_chdir_through_relative_link(self):
self.check_posix_only()
- dir1_path = self.make_path('x', 'foo')
- dir2_path = self.make_path('x', 'bar')
+ dir1_path = self.make_path("x", "foo")
+ dir2_path = self.make_path("x", "bar")
self.create_dir(dir1_path)
self.create_dir(dir2_path)
- link_path = self.make_path('x', 'foo', 'bar')
- self.create_symlink(link_path,
- self.os.path.join('..', 'bar'))
+ link_path = self.make_path("x", "foo", "bar")
+ self.create_symlink(link_path, self.os.path.join("..", "bar"))
self.assert_equal_paths(dir2_path, self.os.path.realpath(link_path))
self.os.chdir(dir1_path)
self.assert_equal_paths(dir1_path, self.os.getcwd())
- self.assert_equal_paths(dir2_path, self.os.path.realpath('bar'))
+ self.assert_equal_paths(dir2_path, self.os.path.realpath("bar"))
- self.os.chdir('bar')
+ self.os.chdir("bar")
self.assert_equal_paths(dir2_path, self.os.getcwd())
def test_chdir_uses_open_fd_as_path(self):
@@ -1916,9 +1994,8 @@ class ResolvePathTest(FakeFileOpenTestBase):
if self.is_pypy:
# unclear behavior with PyPi
self.skip_real_fs()
- self.assert_raises_os_error(
- [errno.ENOTDIR, errno.EBADF], self.os.chdir, 500)
- dir_path = self.make_path('foo', 'bar')
+ self.assert_raises_os_error([errno.ENOTDIR, errno.EBADF], self.os.chdir, 500)
+ dir_path = self.make_path("foo", "bar")
self.create_dir(dir_path)
path_des = self.os.open(dir_path, os.O_RDONLY)
@@ -1930,54 +2007,55 @@ class ResolvePathTest(FakeFileOpenTestBase):
# Write into the final link target and read back from a file which will
# point to that.
self.skip_if_symlink_not_supported()
- link_path = self.make_path('foo', 'bar')
- self.create_symlink(link_path, 'link')
- self.create_symlink(self.make_path('foo', 'link'), 'baz')
- self.write_to_file(self.make_path('foo', 'baz'))
- fh = self.open(link_path, 'r')
- self.assertEqual('x', fh.read())
+ link_path = self.make_path("foo", "bar")
+ self.create_symlink(link_path, "link")
+ self.create_symlink(self.make_path("foo", "link"), "baz")
+ self.write_to_file(self.make_path("foo", "baz"))
+ fh = self.open(link_path, "r")
+ self.assertEqual("x", fh.read())
def test_write_link_to_link(self):
self.skip_if_symlink_not_supported()
- final_target = self.make_path('foo', 'baz')
- link_path = self.make_path('foo', 'bar')
- self.create_symlink(link_path, 'link')
- self.create_symlink(self.make_path('foo', 'link'), 'baz')
+ final_target = self.make_path("foo", "baz")
+ link_path = self.make_path("foo", "bar")
+ self.create_symlink(link_path, "link")
+ self.create_symlink(self.make_path("foo", "link"), "baz")
self.write_to_file(link_path)
self.assertTrue(self.os.path.exists(final_target))
def test_multiple_links(self):
self.skip_if_symlink_not_supported()
- self.os.makedirs(self.make_path('a', 'link1', 'c', 'link2'))
+ self.os.makedirs(self.make_path("a", "link1", "c", "link2"))
- self.create_symlink(self.make_path('a', 'b'), 'link1')
+ self.create_symlink(self.make_path("a", "b"), "link1")
if not self.is_windows:
- self.assert_equal_paths(self.make_path('a', 'link1'),
- self.os.path.realpath(
- self.make_path('a', 'b')))
- self.assert_equal_paths(self.make_path('a', 'link1', 'c'),
- self.os.path.realpath(
- self.make_path('a', 'b', 'c')))
-
- link_path = self.make_path('a', 'link1', 'c', 'd')
- self.create_symlink(link_path, 'link2')
+ self.assert_equal_paths(
+ self.make_path("a", "link1"),
+ self.os.path.realpath(self.make_path("a", "b")),
+ )
+ self.assert_equal_paths(
+ self.make_path("a", "link1", "c"),
+ self.os.path.realpath(self.make_path("a", "b", "c")),
+ )
+
+ link_path = self.make_path("a", "link1", "c", "d")
+ self.create_symlink(link_path, "link2")
self.assertTrue(self.os.path.exists(link_path))
- self.assertTrue(self.os.path.exists(
- self.make_path('a', 'b', 'c', 'd')))
+ self.assertTrue(self.os.path.exists(self.make_path("a", "b", "c", "d")))
- final_target = self.make_path('a', 'link1', 'c', 'link2', 'e')
+ final_target = self.make_path("a", "link1", "c", "link2", "e")
self.assertFalse(self.os.path.exists(final_target))
- self.write_to_file(self.make_path('a', 'b', 'c', 'd', 'e'))
+ self.write_to_file(self.make_path("a", "b", "c", "d", "e"))
self.assertTrue(self.os.path.exists(final_target))
def test_utime_link(self):
"""os.utime() and os.stat() via symbolic link (issue #49)"""
self.skip_if_symlink_not_supported()
- self.create_dir(self.make_path('foo', 'baz'))
- target_path = self.make_path('foo', 'baz', 'bip')
+ self.create_dir(self.make_path("foo", "baz"))
+ target_path = self.make_path("foo", "baz", "bip")
self.write_to_file(target_path)
- link_name = self.make_path('foo', 'bar')
+ link_name = self.make_path("foo", "bar")
self.create_symlink(link_name, target_path)
self.os.utime(link_name, (1, 2))
@@ -1991,21 +2069,21 @@ class ResolvePathTest(FakeFileOpenTestBase):
def test_too_many_links(self):
self.check_posix_only()
- link_path = self.make_path('a', 'loop')
- self.create_symlink(link_path, 'loop')
+ link_path = self.make_path("a", "loop")
+ self.create_symlink(link_path, "loop")
self.assertFalse(self.os.path.exists(link_path))
def test_that_drive_letters_are_preserved(self):
self.check_windows_only()
self.skip_real_fs()
- self.assertEqual('C:!foo!bar',
- self.filesystem.resolve_path('C:!foo!!bar'))
+ self.assertEqual("C:!foo!bar", self.filesystem.resolve_path("C:!foo!!bar"))
def test_that_unc_paths_are_preserved(self):
self.check_windows_only()
self.skip_real_fs()
- self.assertEqual('!!foo!bar!baz',
- self.filesystem.resolve_path('!!foo!bar!baz!!'))
+ self.assertEqual(
+ "!!foo!bar!baz", self.filesystem.resolve_path("!!foo!bar!baz!!")
+ )
class RealResolvePathTest(ResolvePathTest):
@@ -2013,5 +2091,5 @@ class RealResolvePathTest(ResolvePathTest):
return True
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
diff --git a/pyfakefs/tests/fake_os_test.py b/pyfakefs/tests/fake_os_test.py
index 7408d17..6b48bbf 100644
--- a/pyfakefs/tests/fake_os_test.py
+++ b/pyfakefs/tests/fake_os_test.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
#
# Copyright 2009 Google Inc. All Rights Reserved.
#
@@ -14,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-"""Unit tests for fake_filesystem.FakeOpen."""
+"""Unit tests for fake_os.FakeOsModule."""
import errno
import os
@@ -22,12 +21,19 @@ import stat
import sys
import unittest
-from pyfakefs.helpers import IN_DOCKER, IS_PYPY
+from pyfakefs.helpers import IN_DOCKER, IS_PYPY, get_uid, get_gid
-from pyfakefs import fake_filesystem
-from pyfakefs.fake_filesystem import FakeFileOpen, is_root
+from pyfakefs import fake_filesystem, fake_os, fake_open, fake_file
+from pyfakefs.fake_filesystem import (
+ FakeFileOpen,
+ is_root,
+ set_uid,
+ set_gid,
+)
from pyfakefs.extra_packages import (
- use_scandir, use_scandir_package, use_builtin_scandir
+ use_scandir,
+ use_scandir_package,
+ use_builtin_scandir,
)
from pyfakefs.tests.test_utils import TestCase, RealFsTestCase
@@ -59,62 +65,64 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_chdir(self):
"""chdir should work on a directory."""
- directory = self.make_path('foo')
+ directory = self.make_path("foo")
self.create_dir(directory)
self.os.chdir(directory)
def test_chdir_fails_non_exist(self):
"""chdir should raise OSError if the target does not exist."""
- directory = self.make_path('no', 'such', 'directory')
+ directory = self.make_path("no", "such", "directory")
self.assert_raises_os_error(errno.ENOENT, self.os.chdir, directory)
def test_chdir_fails_non_directory(self):
"""chdir should raise OSError if the target is not a directory."""
- filename = self.make_path('foo', 'bar')
+ filename = self.make_path("foo", "bar")
self.create_file(filename)
self.assert_raises_os_error(errno.ENOTDIR, self.os.chdir, filename)
def test_consecutive_chdir(self):
"""Consecutive relative chdir calls should work."""
- dir1 = self.make_path('foo')
- dir2 = 'bar'
+ dir1 = self.make_path("foo")
+ dir2 = "bar"
full_dirname = self.os.path.join(dir1, dir2)
self.create_dir(full_dirname)
self.os.chdir(dir1)
self.os.chdir(dir2)
# use real path to handle symlink /var to /private/var in MacOs
- self.assertEqual(os.path.realpath(self.os.getcwd()),
- os.path.realpath(full_dirname))
+ self.assertEqual(
+ os.path.realpath(self.os.getcwd()), os.path.realpath(full_dirname)
+ )
def test_backwards_chdir(self):
"""chdir into '..' should behave appropriately."""
# skipping real fs test - can't test root dir
self.skip_real_fs()
rootdir = self.os.getcwd()
- dirname = 'foo'
+ dirname = "foo"
abs_dirname = self.os.path.abspath(dirname)
self.filesystem.create_dir(dirname)
self.os.chdir(dirname)
self.assertEqual(abs_dirname, self.os.getcwd())
- self.os.chdir('..')
+ self.os.chdir("..")
self.assertEqual(rootdir, self.os.getcwd())
- self.os.chdir(self.os.path.join(dirname, '..'))
+ self.os.chdir(self.os.path.join(dirname, ".."))
self.assertEqual(rootdir, self.os.getcwd())
def test_get_cwd(self):
# skipping real fs test - can't test root dir
self.skip_real_fs()
- dirname = self.make_path('foo', 'bar')
+ dirname = self.make_path("foo", "bar")
self.create_dir(dirname)
- self.assertEqual(self.os.getcwd(), self.os.path.sep)
+ self.assertEqual(self.filesystem.root_dir_name, self.os.getcwd())
self.os.chdir(dirname)
- self.assertEqual(self.os.getcwd(), dirname)
+ self.assertEqual(dirname, self.os.getcwd())
def test_listdir(self):
self.assert_raises_os_error(
- errno.ENOENT, self.os.listdir, 'non_existing/fake_dir')
- directory = self.make_path('xyzzy', 'plugh')
- files = ['foo', 'bar', 'baz']
+ errno.ENOENT, self.os.listdir, "non_existing/fake_dir"
+ )
+ directory = self.make_path("xyzzy", "plugh")
+ files = ["foo", "bar", "baz"]
for f in files:
self.create_file(self.os.path.join(directory, f))
files.sort()
@@ -125,8 +133,8 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
if os.listdir not in os.supports_fd:
self.skip_real_fs()
self.assert_raises_os_error(errno.EBADF, self.os.listdir, 500)
- dir_path = self.make_path('xyzzy', 'plugh')
- files = ['foo', 'bar', 'baz']
+ dir_path = self.make_path("xyzzy", "plugh")
+ files = ["foo", "bar", "baz"]
for f in files:
self.create_file(self.os.path.join(dir_path, f))
files.sort()
@@ -135,43 +143,42 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.assertEqual(files, sorted(self.os.listdir(path_des)))
def test_listdir_returns_list(self):
- directory_root = self.make_path('xyzzy')
+ directory_root = self.make_path("xyzzy")
self.os.mkdir(directory_root)
- directory = self.os.path.join(directory_root, 'bug')
+ directory = self.os.path.join(directory_root, "bug")
self.os.mkdir(directory)
- self.create_file(self.make_path(directory, 'foo'))
- self.assertEqual(['foo'], self.os.listdir(directory))
+ self.create_file(self.make_path(directory, "foo"))
+ self.assertEqual(["foo"], self.os.listdir(directory))
def test_listdir_on_symlink(self):
self.skip_if_symlink_not_supported()
- directory = self.make_path('xyzzy')
- files = ['foo', 'bar', 'baz']
+ directory = self.make_path("xyzzy")
+ files = ["foo", "bar", "baz"]
for f in files:
self.create_file(self.make_path(directory, f))
- self.create_symlink(self.make_path('symlink'), self.make_path('xyzzy'))
+ self.create_symlink(self.make_path("symlink"), self.make_path("xyzzy"))
files.sort()
- self.assertEqual(files,
- sorted(self.os.listdir(self.make_path('symlink'))))
+ self.assertEqual(files, sorted(self.os.listdir(self.make_path("symlink"))))
def test_listdir_error(self):
- file_path = self.make_path('foo', 'bar', 'baz')
+ file_path = self.make_path("foo", "bar", "baz")
self.create_file(file_path)
self.assert_raises_os_error(errno.ENOTDIR, self.os.listdir, file_path)
def test_exists_current_dir(self):
- self.assertTrue(self.os.path.exists('.'))
+ self.assertTrue(self.os.path.exists("."))
def test_listdir_current(self):
- files = ['foo', 'bar', 'baz']
+ files = ["foo", "bar", "baz"]
for f in files:
self.create_file(self.make_path(f))
files.sort()
self.assertEqual(files, sorted(self.os.listdir(self.base_path)))
def test_fdopen(self):
- file_path1 = self.make_path('some_file1')
- self.create_file(file_path1, contents='contents here1')
- with self.open(file_path1, 'r') as fake_file1:
+ file_path1 = self.make_path("some_file1")
+ self.create_file(file_path1, contents="contents here1")
+ with self.open(file_path1, "r") as fake_file1:
fileno = fake_file1.fileno()
fake_file2 = self.os.fdopen(fileno)
self.assertNotEqual(fake_file2, fake_file1)
@@ -179,23 +186,23 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
with self.assertRaises(TypeError):
self.os.fdopen(None)
with self.assertRaises(TypeError):
- self.os.fdopen('a string')
+ self.os.fdopen("a string")
def test_out_of_range_fdopen(self):
# test some file descriptor that is clearly out of range
self.assert_raises_os_error(errno.EBADF, self.os.fdopen, 500)
def test_closed_file_descriptor(self):
- first_path = self.make_path('some_file1')
- second_path = self.make_path('some_file2')
- third_path = self.make_path('some_file3')
- self.create_file(first_path, contents='contents here1')
- self.create_file(second_path, contents='contents here2')
- self.create_file(third_path, contents='contents here3')
-
- fake_file1 = self.open(first_path, 'r')
- fake_file2 = self.open(second_path, 'r')
- fake_file3 = self.open(third_path, 'r')
+ first_path = self.make_path("some_file1")
+ second_path = self.make_path("some_file2")
+ third_path = self.make_path("some_file3")
+ self.create_file(first_path, contents="contents here1")
+ self.create_file(second_path, contents="contents here2")
+ self.create_file(third_path, contents="contents here3")
+
+ fake_file1 = self.open(first_path, "r")
+ fake_file2 = self.open(second_path, "r")
+ fake_file3 = self.open(third_path, "r")
fileno1 = fake_file1.fileno()
fileno2 = fake_file2.fileno()
fileno3 = fake_file3.fileno()
@@ -213,25 +220,25 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_fdopen_mode(self):
self.skip_real_fs()
- file_path1 = self.make_path('some_file1')
- self.create_file(file_path1, contents='contents here1')
+ file_path1 = self.make_path("some_file1")
+ self.create_file(file_path1, contents="contents here1")
self.os.chmod(file_path1, (stat.S_IFREG | 0o666) ^ stat.S_IWRITE)
- fake_file1 = self.open(file_path1, 'r')
+ fake_file1 = self.open(file_path1, "r")
fileno1 = fake_file1.fileno()
self.os.fdopen(fileno1)
- self.os.fdopen(fileno1, 'r')
+ self.os.fdopen(fileno1, "r")
if not is_root():
with self.assertRaises(OSError):
- self.os.fdopen(fileno1, 'w')
+ self.os.fdopen(fileno1, "w")
else:
- self.os.fdopen(fileno1, 'w')
+ self.os.fdopen(fileno1, "w")
self.os.close(fileno1)
def test_fstat(self):
- directory = self.make_path('xyzzy')
- file_path = self.os.path.join(directory, 'plugh')
- self.create_file(file_path, contents='ABCDE')
+ directory = self.make_path("xyzzy")
+ file_path = self.os.path.join(directory, "plugh")
+ self.create_file(file_path, contents="ABCDE")
with self.open(file_path) as file_obj:
fileno = file_obj.fileno()
self.assertTrue(stat.S_IFREG & self.os.fstat(fileno)[stat.ST_MODE])
@@ -239,20 +246,45 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.assertEqual(5, self.os.fstat(fileno)[stat.ST_SIZE])
def test_stat(self):
- directory = self.make_path('xyzzy')
- file_path = self.os.path.join(directory, 'plugh')
- self.create_file(file_path, contents='ABCDE')
+ directory = self.make_path("xyzzy")
+ file_path = self.os.path.join(directory, "plugh")
+ self.create_file(file_path, contents="ABCDE")
self.assertTrue(stat.S_IFDIR & self.os.stat(directory)[stat.ST_MODE])
self.assertTrue(stat.S_IFREG & self.os.stat(file_path)[stat.ST_MODE])
self.assertTrue(stat.S_IFREG & self.os.stat(file_path).st_mode)
self.assertEqual(5, self.os.stat(file_path)[stat.ST_SIZE])
+ def test_st_blocks(self):
+ self.check_posix_only()
+ file_path = self.make_path("foo1")
+ self.create_file(file_path, contents=b"")
+ self.assertEqual(0, self.os.stat(file_path).st_blocks)
+ file_path = self.make_path("foo2")
+ self.create_file(file_path, contents=b"t")
+ self.assertEqual(8, self.os.stat(file_path).st_blocks)
+ file_path = self.make_path("foo3")
+ self.create_file(file_path, contents=b"t" * 4095)
+ self.assertEqual(8, self.os.stat(file_path).st_blocks)
+ file_path = self.make_path("foo4")
+ self.create_file(file_path, contents=b"t" * 4096)
+ self.assertEqual(8, self.os.stat(file_path).st_blocks)
+ file_path = self.make_path("foo5")
+ self.create_file(file_path, contents=b"t" * 4097)
+ self.assertEqual(16, self.os.stat(file_path).st_blocks)
+
+ def test_no_st_blocks_in_windows(self):
+ self.check_windows_only()
+ file_path = self.make_path("foo")
+ self.create_file(file_path, contents=b"")
+ with self.assertRaises(AttributeError):
+ self.os.stat(file_path).st_blocks
+
def test_stat_with_unc_path(self):
self.skip_real_fs()
self.check_windows_only()
- directory = '//root/share/dir'
- file_path = self.os.path.join(directory, 'plugh')
- self.create_file(file_path, contents='ABCDE')
+ directory = "//root/share/dir"
+ file_path = self.os.path.join(directory, "plugh")
+ self.create_file(file_path, contents="ABCDE")
self.assertTrue(stat.S_IFDIR & self.os.stat(directory)[stat.ST_MODE])
self.assertTrue(stat.S_IFREG & self.os.stat(file_path)[stat.ST_MODE])
self.assertTrue(stat.S_IFREG & self.os.stat(file_path).st_mode)
@@ -261,9 +293,9 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_stat_with_drive(self):
self.skip_real_fs()
self.check_windows_only()
- directory = 'C:/foo/dir'
- file_path = self.os.path.join(directory, 'plugh')
- self.create_file(file_path, contents='ABCDE')
+ directory = "C:/foo/dir"
+ file_path = self.os.path.join(directory, "plugh")
+ self.create_file(file_path, contents="ABCDE")
self.assertTrue(stat.S_IFDIR & self.os.stat(directory)[stat.ST_MODE])
self.assertTrue(stat.S_IFREG & self.os.stat(file_path)[stat.ST_MODE])
self.assertTrue(stat.S_IFREG & self.os.stat(file_path).st_mode)
@@ -272,141 +304,144 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_stat_uses_open_fd_as_path(self):
self.skip_real_fs()
self.assert_raises_os_error(errno.EBADF, self.os.stat, 5)
- file_path = self.make_path('foo', 'bar')
+ file_path = self.make_path("foo", "bar")
self.create_file(file_path)
with self.open(file_path) as f:
- self.assertTrue(
- stat.S_IFREG & self.os.stat(f.filedes)[stat.ST_MODE])
+ self.assertTrue(stat.S_IFREG & self.os.stat(f.filedes)[stat.ST_MODE])
def test_stat_no_follow_symlinks_posix(self):
"""Test that stat with follow_symlinks=False behaves like lstat."""
self.check_posix_only()
- directory = self.make_path('xyzzy')
- base_name = 'plugh'
- file_contents = 'frobozz'
+ directory = self.make_path("xyzzy")
+ base_name = "plugh"
+ file_contents = "frobozz"
# Just make sure we didn't accidentally make our test data meaningless.
self.assertNotEqual(len(base_name), len(file_contents))
file_path = self.os.path.join(directory, base_name)
- link_path = self.os.path.join(directory, 'link')
+ link_path = self.os.path.join(directory, "link")
self.create_file(file_path, contents=file_contents)
self.create_symlink(link_path, base_name)
- self.assertEqual(len(file_contents),
- self.os.stat(file_path, follow_symlinks=False)[
- stat.ST_SIZE])
- self.assertEqual(len(base_name),
- self.os.stat(link_path, follow_symlinks=False)[
- stat.ST_SIZE])
+ self.assertEqual(
+ len(file_contents),
+ self.os.stat(file_path, follow_symlinks=False)[stat.ST_SIZE],
+ )
+ self.assertEqual(
+ len(base_name),
+ self.os.stat(link_path, follow_symlinks=False)[stat.ST_SIZE],
+ )
def test_stat_no_follow_symlinks_windows(self):
"""Test that stat with follow_symlinks=False behaves like lstat."""
self.check_windows_only()
self.skip_if_symlink_not_supported()
- directory = self.make_path('xyzzy')
- base_name = 'plugh'
- file_contents = 'frobozz'
+ directory = self.make_path("xyzzy")
+ base_name = "plugh"
+ file_contents = "frobozz"
# Just make sure we didn't accidentally make our test data meaningless.
self.assertNotEqual(len(base_name), len(file_contents))
file_path = self.os.path.join(directory, base_name)
- link_path = self.os.path.join(directory, 'link')
+ link_path = self.os.path.join(directory, "link")
self.create_file(file_path, contents=file_contents)
self.create_symlink(link_path, base_name)
- self.assertEqual(len(file_contents),
- self.os.stat(file_path, follow_symlinks=False)[
- stat.ST_SIZE])
- self.assertEqual(0,
- self.os.stat(link_path, follow_symlinks=False)[
- stat.ST_SIZE])
+ self.assertEqual(
+ len(file_contents),
+ self.os.stat(file_path, follow_symlinks=False)[stat.ST_SIZE],
+ )
+ self.assertEqual(
+ 0, self.os.stat(link_path, follow_symlinks=False)[stat.ST_SIZE]
+ )
def test_lstat_size_posix(self):
self.check_posix_only()
- directory = self.make_path('xyzzy')
- base_name = 'plugh'
- file_contents = 'frobozz'
+ directory = self.make_path("xyzzy")
+ base_name = "plugh"
+ file_contents = "frobozz"
# Just make sure we didn't accidentally make our test data meaningless.
self.assertNotEqual(len(base_name), len(file_contents))
file_path = self.os.path.join(directory, base_name)
- link_path = self.os.path.join(directory, 'link')
+ link_path = self.os.path.join(directory, "link")
self.create_file(file_path, contents=file_contents)
self.create_symlink(link_path, base_name)
- self.assertEqual(len(file_contents),
- self.os.lstat(file_path)[stat.ST_SIZE])
- self.assertEqual(len(base_name),
- self.os.lstat(link_path)[stat.ST_SIZE])
+ self.assertEqual(len(file_contents), self.os.lstat(file_path)[stat.ST_SIZE])
+ self.assertEqual(len(base_name), self.os.lstat(link_path)[stat.ST_SIZE])
def test_lstat_size_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- directory = self.make_path('xyzzy')
- base_name = 'plugh'
- file_contents = 'frobozz'
+ directory = self.make_path("xyzzy")
+ base_name = "plugh"
+ file_contents = "frobozz"
# Just make sure we didn't accidentally make our test data meaningless.
self.assertNotEqual(len(base_name), len(file_contents))
file_path = self.os.path.join(directory, base_name)
- link_path = self.os.path.join(directory, 'link')
+ link_path = self.os.path.join(directory, "link")
self.create_file(file_path, contents=file_contents)
self.create_symlink(link_path, base_name)
- self.assertEqual(len(file_contents),
- self.os.lstat(file_path)[stat.ST_SIZE])
- self.assertEqual(0,
- self.os.lstat(link_path)[stat.ST_SIZE])
+ self.assertEqual(len(file_contents), self.os.lstat(file_path)[stat.ST_SIZE])
+ self.assertEqual(0, self.os.lstat(link_path)[stat.ST_SIZE])
def test_lstat_trailing_sep(self):
# regression test for #342
stat_result = self.os.lstat(self.base_path)
- self.assertEqual(stat_result,
- self.os.lstat(self.base_path + self.path_separator()))
- self.assertEqual(stat_result, self.os.lstat(
- self.base_path + self.path_separator() + self.path_separator()))
+ self.assertEqual(
+ stat_result, self.os.lstat(self.base_path + self.path_separator())
+ )
+ self.assertEqual(
+ stat_result,
+ self.os.lstat(
+ self.base_path + self.path_separator() + self.path_separator()
+ ),
+ )
def test_stat_with_byte_string(self):
stat_str = self.os.stat(self.base_path)
- base_path_bytes = self.base_path.encode('utf8')
+ base_path_bytes = self.base_path.encode("utf8")
stat_bytes = self.os.stat(base_path_bytes)
self.assertEqual(stat_bytes, stat_str)
def test_lstat_with_byte_string(self):
stat_str = self.os.lstat(self.base_path)
- base_path_bytes = self.base_path.encode('utf8')
+ base_path_bytes = self.base_path.encode("utf8")
stat_bytes = self.os.lstat(base_path_bytes)
self.assertEqual(stat_bytes, stat_str)
def test_stat_with_current_dir(self):
# regression test for #516
- stat_result = self.os.stat('.')
- lstat_result = self.os.lstat('.')
+ stat_result = self.os.stat(".")
+ lstat_result = self.os.lstat(".")
self.assertEqual(stat_result, lstat_result)
def test_exists_with_trailing_sep(self):
# regression test for #364
- file_path = self.make_path('alpha')
+ file_path = self.make_path("alpha")
self.create_file(file_path)
self.assertFalse(self.os.path.exists(file_path + self.os.sep))
def test_mkdir_with_trailing_sep(self):
# regression test for #367
- dir_path = self.make_path('foo')
+ dir_path = self.make_path("foo")
self.os.mkdir(dir_path + self.os.sep + self.os.sep)
self.assertTrue(self.os.path.exists(dir_path))
def test_readlink_empty_path(self):
self.check_posix_only()
- self.assert_raises_os_error(errno.ENOENT,
- self.os.readlink, '')
+ self.assert_raises_os_error(errno.ENOENT, self.os.readlink, "")
def test_readlink_ending_with_sep_posix(self):
# regression test for #359
self.check_posix_only()
- link_path = self.make_path('foo')
+ link_path = self.make_path("foo")
self.os.symlink(self.base_path, link_path)
- self.assert_raises_os_error(errno.EINVAL,
- self.os.readlink, link_path + self.os.sep)
+ self.assert_raises_os_error(
+ errno.EINVAL, self.os.readlink, link_path + self.os.sep
+ )
def test_lstat_symlink_with_trailing_sep_linux(self):
# regression test for #366
self.check_linux_only()
self.skip_if_symlink_not_supported()
- link_path = self.make_path('foo')
+ link_path = self.make_path("foo")
self.os.symlink(self.base_path, link_path)
# used to raise
self.assertTrue(self.os.lstat(link_path + self.os.sep).st_mode)
@@ -415,7 +450,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
# regression test for #366
self.check_macos_only()
self.skip_if_symlink_not_supported()
- link_path = self.make_path('foo')
+ link_path = self.make_path("foo")
self.os.symlink(self.base_path, link_path)
# used to raise
self.assertTrue(self.os.lstat(link_path + self.os.sep).st_mode)
@@ -423,35 +458,37 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_readlink_ending_with_sep_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- link_path = self.make_path('foo')
+ link_path = self.make_path("foo")
self.os.symlink(self.base_path, link_path)
- self.assert_equal_paths(self.base_path,
- self.os.readlink(link_path + self.os.sep))
+ self.assert_equal_paths(
+ self.base_path, self.os.readlink(link_path + self.os.sep)
+ )
def test_islink_with_trailing_sep_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- link_path = self.make_path('foo')
+ link_path = self.make_path("foo")
self.os.symlink(self.base_path, link_path)
self.assertTrue(self.os.path.islink(link_path + self.os.path.sep))
def test_islink_with_trailing_sep_linux(self):
self.check_linux_only()
- link_path = self.make_path('foo')
+ link_path = self.make_path("foo")
self.os.symlink(self.base_path, link_path)
self.assertFalse(self.os.path.islink(link_path + self.os.sep))
def test_islink_with_trailing_sep_macos(self):
self.check_macos_only()
- link_path = self.make_path('foo')
+ link_path = self.make_path("foo")
self.os.symlink(self.base_path, link_path)
self.assertFalse(self.os.path.islink(link_path + self.os.sep))
def check_getsize_raises_with_trailing_separator(self, error_nr):
- file_path = self.make_path('bar')
+ file_path = self.make_path("bar")
self.create_file(file_path)
- self.assert_raises_os_error(error_nr, self.os.path.getsize,
- file_path + self.os.sep)
+ self.assert_raises_os_error(
+ error_nr, self.os.path.getsize, file_path + self.os.sep
+ )
def test_getsize_raises_with_trailing_separator_posix(self):
self.check_posix_only()
@@ -463,10 +500,9 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def check_remove_link_ending_with_sep(self, error_nr):
# regression test for #360
- link_path = self.make_path('foo')
+ link_path = self.make_path("foo")
self.os.symlink(self.base_path, link_path)
- self.assert_raises_os_error(error_nr,
- self.os.remove, link_path + self.os.sep)
+ self.assert_raises_os_error(error_nr, self.os.remove, link_path + self.os.sep)
def test_remove_link_ending_with_sep_linux(self):
self.check_linux_only()
@@ -486,34 +522,36 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
if os.lstat not in os.supports_fd:
self.skip_real_fs()
self.assert_raises_os_error(errno.EBADF, self.os.lstat, 5)
- file_path = self.make_path('foo', 'bar')
- link_path = self.make_path('foo', 'link')
- file_contents = b'contents'
+ file_path = self.make_path("foo", "bar")
+ link_path = self.make_path("foo", "link")
+ file_contents = b"contents"
self.create_file(file_path, contents=file_contents)
self.create_symlink(link_path, file_path)
with self.open(file_path) as f:
- self.assertEqual(len(file_contents),
- self.os.lstat(f.filedes)[stat.ST_SIZE])
+ self.assertEqual(len(file_contents), self.os.lstat(f.filedes)[stat.ST_SIZE])
def test_stat_non_existent_file(self):
# set up
- file_path = self.make_path('non', 'existent', 'file')
+ file_path = self.make_path("non", "existent", "file")
self.assertFalse(self.os.path.exists(file_path))
# actual tests
try:
# Use try-catch to check exception attributes.
self.os.stat(file_path)
- self.fail('Exception is expected.') # COV_NF_LINE
+ self.fail("Exception is expected.") # COV_NF_LINE
except OSError as os_error:
self.assertEqual(errno.ENOENT, os_error.errno)
self.assertEqual(file_path, os_error.filename)
def check_open_raises_with_trailing_separator(self, error_nr):
- file_path = self.make_path('bar') + self.os.sep
- self.assert_raises_os_error(error_nr, self.os.open,
- file_path,
- os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
+ file_path = self.make_path("bar") + self.os.sep
+ self.assert_raises_os_error(
+ error_nr,
+ self.os.open,
+ file_path,
+ os.O_CREAT | os.O_WRONLY | os.O_TRUNC,
+ )
def test_open_raises_with_trailing_separator_linux(self):
self.check_linux_only()
@@ -530,55 +568,54 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_lexists_with_trailing_separator_linux_windows(self):
self.check_linux_and_windows()
self.skip_if_symlink_not_supported()
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.os.symlink(file_path, file_path)
self.assertFalse(self.os.path.lexists(file_path + self.os.sep))
def test_lexists_with_trailing_separator_macos(self):
# regression test for #373
self.check_macos_only()
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.os.symlink(file_path, file_path)
self.assertTrue(self.os.path.lexists(file_path + self.os.sep))
def test_islink_with_trailing_separator_linux_windows(self):
self.check_linux_and_windows()
self.skip_if_symlink_not_supported()
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.os.symlink(file_path, file_path)
self.assertFalse(self.os.path.islink(file_path + self.os.sep))
def test_islink_with_trailing_separator_macos(self):
# regression test for #373
self.check_macos_only()
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.os.symlink(file_path, file_path)
self.assertTrue(self.os.path.islink(file_path + self.os.sep))
def test_isfile_with_trailing_separator_linux_windows(self):
self.check_linux_and_windows()
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.create_file(file_path)
self.assertFalse(self.os.path.isfile(file_path + self.os.sep))
def test_isfile_with_trailing_separator_macos(self):
# regression test for #374
self.check_macos_only()
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.create_file(file_path)
self.assertFalse(self.os.path.isfile(file_path + self.os.sep))
def test_isfile_not_readable_file(self):
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.create_file(file_path, perm=0)
self.assertTrue(self.os.path.isfile(file_path))
def check_stat_with_trailing_separator(self, error_nr):
# regression test for #376
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.create_file(file_path)
- self.assert_raises_os_error(error_nr, self.os.stat,
- file_path + self.os.sep)
+ self.assert_raises_os_error(error_nr, self.os.stat, file_path + self.os.sep)
def test_stat_with_trailing_separator_posix(self):
self.check_posix_only()
@@ -590,10 +627,9 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def check_remove_with_trailing_separator(self, error_nr):
# regression test for #377
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.create_file(file_path)
- self.assert_raises_os_error(error_nr, self.os.remove,
- file_path + self.os.sep)
+ self.assert_raises_os_error(error_nr, self.os.remove, file_path + self.os.sep)
def test_remove_with_trailing_separator_posix(self):
self.check_posix_only()
@@ -605,13 +641,13 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_readlink(self):
self.skip_if_symlink_not_supported()
- link_path = self.make_path('foo', 'bar', 'baz')
- target = self.make_path('tarJAY')
+ link_path = self.make_path("foo", "bar", "baz")
+ target = self.make_path("tarJAY")
self.create_symlink(link_path, target)
self.assert_equal_paths(self.os.readlink(link_path), target)
def check_readlink_raises_if_path_is_not_a_link(self):
- file_path = self.make_path('foo', 'bar', 'eleventyone')
+ file_path = self.make_path("foo", "bar", "eleventyone")
self.create_file(file_path)
self.assert_raises_os_error(errno.EINVAL, self.os.readlink, file_path)
@@ -625,10 +661,10 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.check_readlink_raises_if_path_is_not_a_link()
def check_readlink_raises_if_path_has_file(self, error_subtype):
- self.create_file(self.make_path('a_file'))
- file_path = self.make_path('a_file', 'foo')
+ self.create_file(self.make_path("a_file"))
+ file_path = self.make_path("a_file", "foo")
self.assert_raises_os_error(error_subtype, self.os.readlink, file_path)
- file_path = self.make_path('a_file', 'foo', 'bar')
+ file_path = self.make_path("a_file", "foo", "bar")
self.assert_raises_os_error(error_subtype, self.os.readlink, file_path)
def test_readlink_raises_if_path_has_file_windows(self):
@@ -642,8 +678,9 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_readlink_raises_if_path_does_not_exist(self):
self.skip_if_symlink_not_supported()
- self.assert_raises_os_error(errno.ENOENT, self.os.readlink,
- '/this/path/does/not/exist')
+ self.assert_raises_os_error(
+ errno.ENOENT, self.os.readlink, "/this/path/does/not/exist"
+ )
def test_readlink_raises_if_path_is_none(self):
self.skip_if_symlink_not_supported()
@@ -652,43 +689,50 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_broken_symlink_with_trailing_separator_linux(self):
self.check_linux_only()
- file_path = self.make_path('foo')
- link_path = self.make_path('link')
+ file_path = self.make_path("foo")
+ link_path = self.make_path("link")
self.os.symlink(file_path, link_path)
- self.assert_raises_os_error(errno.EEXIST, self.os.symlink,
- link_path + self.os.sep,
- link_path + self.os.sep)
+ self.assert_raises_os_error(
+ errno.EEXIST,
+ self.os.symlink,
+ link_path + self.os.sep,
+ link_path + self.os.sep,
+ )
def test_broken_symlink_with_trailing_separator_macos(self):
# regression test for #371
self.check_macos_only()
- file_path = self.make_path('foo')
- link_path = self.make_path('link')
+ file_path = self.make_path("foo")
+ link_path = self.make_path("link")
self.os.symlink(file_path, link_path)
self.os.symlink(link_path + self.os.sep, link_path + self.os.sep)
def test_broken_symlink_with_trailing_separator_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- file_path = self.make_path('foo')
- link_path = self.make_path('link')
+ file_path = self.make_path("foo")
+ link_path = self.make_path("link")
self.os.symlink(file_path, link_path)
- self.assert_raises_os_error(errno.EINVAL, self.os.symlink,
- link_path + self.os.sep,
- link_path + self.os.sep)
+ self.assert_raises_os_error(
+ errno.EINVAL,
+ self.os.symlink,
+ link_path + self.os.sep,
+ link_path + self.os.sep,
+ )
def test_circular_readlink_with_trailing_separator_linux(self):
# Regression test for #372
self.check_linux_only()
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.os.symlink(file_path, file_path)
- self.assert_raises_os_error(errno.ELOOP, self.os.readlink,
- file_path + self.os.sep)
+ self.assert_raises_os_error(
+ errno.ELOOP, self.os.readlink, file_path + self.os.sep
+ )
def test_circular_readlink_with_trailing_separator_macos(self):
# Regression test for #372
self.check_macos_only()
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.os.symlink(file_path, file_path)
self.os.readlink(file_path + self.os.sep)
@@ -696,38 +740,43 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
# Regression test for #372
self.check_windows_only()
self.skip_if_symlink_not_supported()
- file_path = self.make_path('foo')
+ file_path = self.make_path("foo")
self.os.symlink(file_path, file_path)
- self.assert_raises_os_error(errno.EINVAL, self.os.readlink,
- file_path + self.os.sep)
+ self.assert_raises_os_error(
+ errno.EINVAL, self.os.readlink, file_path + self.os.sep
+ )
def test_readlink_with_links_in_path(self):
self.skip_if_symlink_not_supported()
- self.create_symlink(self.make_path('meyer', 'lemon', 'pie'),
- self.make_path('yum'))
- self.create_symlink(self.make_path('geo', 'metro'),
- self.make_path('meyer'))
- self.assert_equal_paths(self.make_path('yum'),
- self.os.readlink(
- self.make_path('geo', 'metro',
- 'lemon', 'pie')))
+ self.create_symlink(
+ self.make_path("meyer", "lemon", "pie"), self.make_path("yum")
+ )
+ self.create_symlink(self.make_path("geo", "metro"), self.make_path("meyer"))
+ self.assert_equal_paths(
+ self.make_path("yum"),
+ self.os.readlink(self.make_path("geo", "metro", "lemon", "pie")),
+ )
def test_readlink_with_chained_links_in_path(self):
self.skip_if_symlink_not_supported()
- self.create_symlink(self.make_path(
- 'eastern', 'european', 'wolfhounds', 'chase'),
- self.make_path('cats'))
- self.create_symlink(self.make_path('russian'),
- self.make_path('eastern', 'european'))
- self.create_symlink(self.make_path('dogs'),
- self.make_path('russian', 'wolfhounds'))
- self.assert_equal_paths(self.make_path('cats'),
- self.os.readlink(
- self.make_path('dogs', 'chase')))
+ self.create_symlink(
+ self.make_path("eastern", "european", "wolfhounds", "chase"),
+ self.make_path("cats"),
+ )
+ self.create_symlink(
+ self.make_path("russian"), self.make_path("eastern", "european")
+ )
+ self.create_symlink(
+ self.make_path("dogs"), self.make_path("russian", "wolfhounds")
+ )
+ self.assert_equal_paths(
+ self.make_path("cats"),
+ self.os.readlink(self.make_path("dogs", "chase")),
+ )
def check_remove_dir(self, dir_error):
- directory = self.make_path('xyzzy')
- dir_path = self.os.path.join(directory, 'plugh')
+ directory = self.make_path("xyzzy")
+ dir_path = self.os.path.join(directory, "plugh")
self.create_dir(dir_path)
self.assertTrue(self.os.path.exists(dir_path))
self.assert_raises_os_error(dir_error, self.os.remove, dir_path)
@@ -735,7 +784,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.os.chdir(directory)
self.assert_raises_os_error(dir_error, self.os.remove, dir_path)
self.assertTrue(self.os.path.exists(dir_path))
- self.assert_raises_os_error(errno.ENOENT, self.os.remove, '/plugh')
+ self.assert_raises_os_error(errno.ENOENT, self.os.remove, "/plugh")
def test_remove_dir_linux(self):
self.check_linux_only()
@@ -753,21 +802,21 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
# regression test for issue #337
self.check_windows_only()
self.skip_real_fs()
- dir_path = self.os.path.join('C:', 'test')
+ dir_path = self.os.path.join("C:", "test")
self.filesystem.create_dir(dir_path)
self.assert_raises_os_error(errno.EACCES, self.os.remove, dir_path)
def test_remove_file(self):
- directory = self.make_path('zzy')
- file_path = self.os.path.join(directory, 'plugh')
+ directory = self.make_path("zzy")
+ file_path = self.os.path.join(directory, "plugh")
self.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path))
self.os.remove(file_path)
self.assertFalse(self.os.path.exists(file_path))
def test_remove_file_no_directory(self):
- directory = self.make_path('zzy')
- file_name = 'plugh'
+ directory = self.make_path("zzy")
+ file_name = "plugh"
file_path = self.os.path.join(directory, file_name)
self.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path))
@@ -777,7 +826,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_remove_file_with_read_permission_raises_in_windows(self):
self.check_windows_only()
- path = self.make_path('foo', 'bar')
+ path = self.make_path("foo", "bar")
self.create_file(path)
self.os.chmod(path, 0o444)
self.assert_raises_os_error(errno.EACCES, self.os.remove, path)
@@ -785,7 +834,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_remove_file_with_read_permission_shall_succeed_in_posix(self):
self.check_posix_only()
- path = self.make_path('foo', 'bar')
+ path = self.make_path("foo", "bar")
self.create_file(path)
self.os.chmod(path, 0o444)
self.os.remove(path)
@@ -793,8 +842,8 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_remove_file_without_parent_permission_raises_in_posix(self):
self.check_posix_only()
- parent_dir = self.make_path('foo')
- path = self.os.path.join(parent_dir, 'bar')
+ parent_dir = self.make_path("foo")
+ path = self.os.path.join(parent_dir, "bar")
self.create_file(path)
self.os.chmod(parent_dir, 0o666) # missing execute permission
if not is_root():
@@ -816,28 +865,28 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_remove_open_file_fails_under_windows(self):
self.check_windows_only()
- path = self.make_path('foo', 'bar')
+ path = self.make_path("foo", "bar")
self.create_file(path)
- with self.open(path, 'r'):
+ with self.open(path, "r"):
self.assert_raises_os_error(errno.EACCES, self.os.remove, path)
self.assertTrue(self.os.path.exists(path))
def test_remove_open_file_possible_under_posix(self):
self.check_posix_only()
- path = self.make_path('foo', 'bar')
+ path = self.make_path("foo", "bar")
self.create_file(path)
- self.open(path, 'r')
+ self.open(path, "r")
self.os.remove(path)
self.assertFalse(self.os.path.exists(path))
def test_remove_file_relative_path(self):
self.skip_real_fs()
original_dir = self.os.getcwd()
- directory = self.make_path('zzy')
- subdirectory = self.os.path.join(directory, 'zzy')
- file_name = 'plugh'
+ directory = self.make_path("zzy")
+ subdirectory = self.os.path.join(directory, "zzy")
+ file_name = "plugh"
file_path = self.os.path.join(directory, file_name)
- file_path_relative = self.os.path.join('..', file_name)
+ file_path_relative = self.os.path.join("..", file_name)
self.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path))
self.create_dir(subdirectory)
@@ -849,7 +898,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.assertFalse(self.os.path.exists(file_path))
def check_remove_dir_raises_error(self, dir_error):
- directory = self.make_path('zzy')
+ directory = self.make_path("zzy")
self.create_dir(directory)
self.assert_raises_os_error(dir_error, self.os.remove, directory)
@@ -867,8 +916,8 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_remove_symlink_to_dir(self):
self.skip_if_symlink_not_supported()
- directory = self.make_path('zzy')
- link = self.make_path('link_to_dir')
+ directory = self.make_path("zzy")
+ link = self.make_path("link_to_dir")
self.create_dir(directory)
self.os.symlink(directory, link)
self.assertTrue(self.os.path.exists(directory))
@@ -878,48 +927,46 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.assertFalse(self.os.path.exists(link))
def test_unlink_raises_if_not_exist(self):
- file_path = self.make_path('file', 'does', 'not', 'exist')
+ file_path = self.make_path("file", "does", "not", "exist")
self.assertFalse(self.os.path.exists(file_path))
self.assert_raises_os_error(errno.ENOENT, self.os.unlink, file_path)
def test_rename_to_nonexistent_file(self):
"""Can rename a file to an unused name."""
- directory = self.make_path('xyzzy')
- old_file_path = self.os.path.join(directory, 'plugh_old')
- new_file_path = self.os.path.join(directory, 'plugh_new')
- self.create_file(old_file_path, contents='test contents')
+ directory = self.make_path("xyzzy")
+ old_file_path = self.os.path.join(directory, "plugh_old")
+ new_file_path = self.os.path.join(directory, "plugh_new")
+ self.create_file(old_file_path, contents="test contents")
self.assertTrue(self.os.path.exists(old_file_path))
self.assertFalse(self.os.path.exists(new_file_path))
self.os.rename(old_file_path, new_file_path)
self.assertFalse(self.os.path.exists(old_file_path))
self.assertTrue(self.os.path.exists(new_file_path))
- self.check_contents(new_file_path, 'test contents')
+ self.check_contents(new_file_path, "test contents")
def test_rename_dir_to_symlink_posix(self):
self.check_posix_only()
- link_path = self.make_path('link')
- dir_path = self.make_path('dir')
- link_target = self.os.path.join(dir_path, 'link_target')
+ link_path = self.make_path("link")
+ dir_path = self.make_path("dir")
+ link_target = self.os.path.join(dir_path, "link_target")
self.create_dir(dir_path)
self.os.symlink(link_target, link_path)
- self.assert_raises_os_error(errno.ENOTDIR, self.os.rename, dir_path,
- link_path)
+ self.assert_raises_os_error(errno.ENOTDIR, self.os.rename, dir_path, link_path)
def test_rename_dir_to_symlink_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- link_path = self.make_path('link')
- dir_path = self.make_path('dir')
- link_target = self.os.path.join(dir_path, 'link_target')
+ link_path = self.make_path("link")
+ dir_path = self.make_path("dir")
+ link_target = self.os.path.join(dir_path, "link_target")
self.create_dir(dir_path)
self.os.symlink(link_target, link_path)
- self.assert_raises_os_error(errno.EEXIST, self.os.rename, dir_path,
- link_path)
+ self.assert_raises_os_error(errno.EEXIST, self.os.rename, dir_path, link_path)
def test_rename_file_to_symlink(self):
self.check_posix_only()
- link_path = self.make_path('file_link')
- file_path = self.make_path('file')
+ link_path = self.make_path("file_link")
+ file_path = self.make_path("file")
self.os.symlink(file_path, link_path)
self.create_file(file_path)
self.os.rename(file_path, link_path)
@@ -929,10 +976,10 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_rename_symlink_to_symlink(self):
self.check_posix_only()
- base_path = self.make_path('foo', 'bar')
+ base_path = self.make_path("foo", "bar")
self.create_dir(base_path)
- link_path1 = self.os.path.join(base_path, 'link1')
- link_path2 = self.os.path.join(base_path, 'link2')
+ link_path1 = self.os.path.join(base_path, "link1")
+ link_path2 = self.os.path.join(base_path, "link2")
self.os.symlink(base_path, link_path1)
self.os.symlink(base_path, link_path2)
self.os.rename(link_path1, link_path2)
@@ -941,72 +988,77 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_rename_symlink_to_symlink_for_parent_raises(self):
self.check_posix_only()
- dir_link = self.make_path('dir_link')
- dir_path = self.make_path('dir')
- dir_in_dir_path = self.os.path.join(dir_link, 'inner_dir')
+ dir_link = self.make_path("dir_link")
+ dir_path = self.make_path("dir")
+ dir_in_dir_path = self.os.path.join(dir_link, "inner_dir")
self.create_dir(dir_path)
self.os.symlink(dir_path, dir_link)
self.create_dir(dir_in_dir_path)
- self.assert_raises_os_error(errno.EINVAL, self.os.rename, dir_path,
- dir_in_dir_path)
+ self.assert_raises_os_error(
+ errno.EINVAL, self.os.rename, dir_path, dir_in_dir_path
+ )
def check_rename_case_with_symlink(self, result):
self.skip_if_symlink_not_supported()
self.check_case_insensitive_fs()
- dir_path_lower = self.make_path('beta')
+ dir_path_lower = self.make_path("beta")
self.create_dir(dir_path_lower)
- link_path = self.make_path('b')
+ link_path = self.make_path("b")
self.os.symlink(self.base_path, link_path)
- path1 = self.os.path.join(link_path, 'Beta')
- dir_path_upper = self.make_path('Beta')
+ path1 = self.os.path.join(link_path, "Beta")
+ dir_path_upper = self.make_path("Beta")
self.os.rename(path1, dir_path_upper)
self.assertEqual(result, sorted(self.os.listdir(self.base_path)))
def test_rename_case_with_symlink_mac(self):
# Regression test for #322
self.check_macos_only()
- self.check_rename_case_with_symlink(['b', 'beta'])
+ self.check_rename_case_with_symlink(["b", "beta"])
def test_rename_case_with_symlink_windows(self):
self.check_windows_only()
- self.check_rename_case_with_symlink(['Beta', 'b'])
+ self.check_rename_case_with_symlink(["Beta", "b"])
def test_recursive_rename_raises(self):
self.check_posix_only()
- base_path = self.make_path('foo', 'bar')
+ base_path = self.make_path("foo", "bar")
self.create_dir(base_path)
- new_path = self.os.path.join(base_path, 'new_dir')
- self.assert_raises_os_error(errno.EINVAL, self.os.rename, base_path,
- new_path)
+ new_path = self.os.path.join(base_path, "new_dir")
+ self.assert_raises_os_error(errno.EINVAL, self.os.rename, base_path, new_path)
def test_rename_file_to_parent_dir_file(self):
# Regression test for issue 230
- dir_path = self.make_path('dir')
+ dir_path = self.make_path("dir")
self.create_dir(dir_path)
- file_path = self.make_path('old_file')
- new_file_path = self.os.path.join(dir_path, 'new_file')
+ file_path = self.make_path("old_file")
+ new_file_path = self.os.path.join(dir_path, "new_file")
self.create_file(file_path)
self.os.rename(file_path, new_file_path)
def test_rename_with_target_parent_file_raises_posix(self):
self.check_posix_only()
- file_path = self.make_path('foo', 'baz')
+ file_path = self.make_path("foo", "baz")
self.create_file(file_path)
- self.assert_raises_os_error(errno.ENOTDIR, self.os.rename, file_path,
- file_path + '/new')
+ self.assert_raises_os_error(
+ errno.ENOTDIR, self.os.rename, file_path, file_path + "/new"
+ )
def test_rename_with_target_parent_file_raises_windows(self):
self.check_windows_only()
- file_path = self.make_path('foo', 'baz')
+ file_path = self.make_path("foo", "baz")
self.create_file(file_path)
- self.assert_raises_os_error(errno.EACCES, self.os.rename, file_path,
- self.os.path.join(file_path, 'new'))
+ self.assert_raises_os_error(
+ errno.EACCES,
+ self.os.rename,
+ file_path,
+ self.os.path.join(file_path, "new"),
+ )
def test_rename_symlink_to_source(self):
self.check_posix_only()
- base_path = self.make_path('foo')
- link_path = self.os.path.join(base_path, 'slink')
- file_path = self.os.path.join(base_path, 'file')
+ base_path = self.make_path("foo")
+ link_path = self.os.path.join(base_path, "slink")
+ file_path = self.os.path.join(base_path, "file")
self.create_file(file_path)
self.os.symlink(file_path, link_path)
self.os.rename(link_path, file_path)
@@ -1014,20 +1066,19 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_rename_symlink_to_dir_raises(self):
self.check_posix_only()
- base_path = self.make_path('foo', 'bar')
- link_path = self.os.path.join(base_path, 'dir_link')
- dir_path = self.os.path.join(base_path, 'dir')
+ base_path = self.make_path("foo", "bar")
+ link_path = self.os.path.join(base_path, "dir_link")
+ dir_path = self.os.path.join(base_path, "dir")
self.create_dir(dir_path)
self.os.symlink(dir_path, link_path)
- self.assert_raises_os_error(errno.EISDIR, self.os.rename, link_path,
- dir_path)
+ self.assert_raises_os_error(errno.EISDIR, self.os.rename, link_path, dir_path)
def test_rename_broken_symlink(self):
self.check_posix_only()
- base_path = self.make_path('foo')
+ base_path = self.make_path("foo")
self.create_dir(base_path)
- link_path = self.os.path.join(base_path, 'slink')
- file_path = self.os.path.join(base_path, 'file')
+ link_path = self.os.path.join(base_path, "slink")
+ file_path = self.os.path.join(base_path, "file")
self.os.symlink(file_path, link_path)
self.os.rename(link_path, file_path)
self.assertFalse(self.os.path.exists(file_path))
@@ -1036,28 +1087,25 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_rename_directory(self):
"""Can rename a directory to an unused name."""
- for old_path, new_path in [('wxyyw', 'xyzzy'), ('abccb', 'cdeed')]:
+ for old_path, new_path in [("wxyyw", "xyzzy"), ("abccb", "cdeed")]:
old_path = self.make_path(old_path)
new_path = self.make_path(new_path)
- self.create_file(self.os.path.join(old_path, 'plugh'),
- contents='test')
+ self.create_file(self.os.path.join(old_path, "plugh"), contents="test")
self.assertTrue(self.os.path.exists(old_path))
self.assertFalse(self.os.path.exists(new_path))
self.os.rename(old_path, new_path)
self.assertFalse(self.os.path.exists(old_path))
self.assertTrue(self.os.path.exists(new_path))
- self.check_contents(self.os.path.join(new_path, 'plugh'), 'test')
+ self.check_contents(self.os.path.join(new_path, "plugh"), "test")
if not self.use_real_fs():
- self.assertEqual(3,
- self.filesystem.get_object(new_path).st_nlink)
+ self.assertEqual(3, self.filesystem.get_object(new_path).st_nlink)
def check_rename_directory_to_existing_file_raises(self, error_nr):
- dir_path = self.make_path('dir')
- file_path = self.make_path('file')
+ dir_path = self.make_path("dir")
+ file_path = self.make_path("file")
self.create_dir(dir_path)
self.create_file(file_path)
- self.assert_raises_os_error(error_nr, self.os.rename, dir_path,
- file_path)
+ self.assert_raises_os_error(error_nr, self.os.rename, dir_path, file_path)
def test_rename_directory_to_existing_file_raises_posix(self):
self.check_posix_only()
@@ -1070,19 +1118,18 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_rename_to_existing_directory_should_raise_under_windows(self):
"""Renaming to an existing directory raises OSError under Windows."""
self.check_windows_only()
- old_path = self.make_path('foo', 'bar')
- new_path = self.make_path('foo', 'baz')
+ old_path = self.make_path("foo", "bar")
+ new_path = self.make_path("foo", "baz")
self.create_dir(old_path)
self.create_dir(new_path)
- self.assert_raises_os_error(errno.EEXIST, self.os.rename, old_path,
- new_path)
+ self.assert_raises_os_error(errno.EEXIST, self.os.rename, old_path, new_path)
def test_rename_to_a_hardlink_of_same_file_should_do_nothing(self):
self.skip_real_fs_failure(skip_posix=False)
self.skip_if_symlink_not_supported()
- file_path = self.make_path('dir', 'file')
+ file_path = self.make_path("dir", "file")
self.create_file(file_path)
- link_path = self.make_path('link')
+ link_path = self.make_path("link")
self.os.link(file_path, link_path)
self.os.rename(file_path, link_path)
self.assertTrue(self.os.path.exists(file_path))
@@ -1090,13 +1137,13 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_hardlink_works_with_symlink(self):
self.skip_if_symlink_not_supported()
- base_path = self.make_path('foo')
+ base_path = self.make_path("foo")
self.create_dir(base_path)
- symlink_path = self.os.path.join(base_path, 'slink')
+ symlink_path = self.os.path.join(base_path, "slink")
self.os.symlink(base_path, symlink_path)
- file_path = self.os.path.join(base_path, 'slink', 'beta')
+ file_path = self.os.path.join(base_path, "slink", "beta")
self.create_file(file_path)
- link_path = self.os.path.join(base_path, 'slink', 'gamma')
+ link_path = self.os.path.join(base_path, "slink", "gamma")
self.os.link(file_path, link_path)
self.assertTrue(self.os.path.exists(link_path))
self.assertFalse(self.os.path.islink(link_path))
@@ -1104,43 +1151,40 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_replace_existing_directory_should_raise_under_windows(self):
"""Renaming to an existing directory raises OSError under Windows."""
self.check_windows_only()
- old_path = self.make_path('foo', 'bar')
- new_path = self.make_path('foo', 'baz')
+ old_path = self.make_path("foo", "bar")
+ new_path = self.make_path("foo", "baz")
self.create_dir(old_path)
self.create_dir(new_path)
- self.assert_raises_os_error(errno.EACCES, self.os.replace, old_path,
- new_path)
+ self.assert_raises_os_error(errno.EACCES, self.os.replace, old_path, new_path)
def test_rename_to_existing_directory_under_posix(self):
"""Renaming to an existing directory changes the existing directory
under Posix."""
self.check_posix_only()
- old_path = self.make_path('foo', 'bar')
- new_path = self.make_path('xyzzy')
- self.create_dir(self.os.path.join(old_path, 'sub'))
+ old_path = self.make_path("foo", "bar")
+ new_path = self.make_path("xyzzy")
+ self.create_dir(self.os.path.join(old_path, "sub"))
self.create_dir(new_path)
self.os.rename(old_path, new_path)
- self.assertTrue(
- self.os.path.exists(self.os.path.join(new_path, 'sub')))
+ self.assertTrue(self.os.path.exists(self.os.path.join(new_path, "sub")))
self.assertFalse(self.os.path.exists(old_path))
def test_rename_file_to_existing_directory_raises_under_posix(self):
self.check_posix_only()
- file_path = self.make_path('foo', 'bar', 'baz')
- new_path = self.make_path('xyzzy')
+ file_path = self.make_path("foo", "bar", "baz")
+ new_path = self.make_path("xyzzy")
self.create_file(file_path)
self.create_dir(new_path)
- self.assert_raises_os_error(errno.EISDIR, self.os.rename, file_path,
- new_path)
+ self.assert_raises_os_error(errno.EISDIR, self.os.rename, file_path, new_path)
def test_rename_to_existing_dir_under_posix_raises_if_not_empty(self):
"""Renaming to an existing directory changes the existing directory
under Posix."""
self.check_posix_only()
- old_path = self.make_path('foo', 'bar')
- new_path = self.make_path('foo', 'baz')
- self.create_dir(self.os.path.join(old_path, 'sub'))
- self.create_dir(self.os.path.join(new_path, 'sub'))
+ old_path = self.make_path("foo", "bar")
+ new_path = self.make_path("foo", "baz")
+ self.create_dir(self.os.path.join(old_path, "sub"))
+ self.create_dir(self.os.path.join(new_path, "sub"))
# not testing specific subtype:
# raises errno.ENOTEMPTY under Ubuntu 16.04, MacOS and pyfakefs
@@ -1151,112 +1195,115 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_rename_to_another_device_should_raise(self):
"""Renaming to another filesystem device raises OSError."""
self.skip_real_fs()
- self.filesystem.add_mount_point('/mount')
- old_path = '/foo/bar'
- new_path = '/mount/bar'
+ self.filesystem.add_mount_point("/mount")
+ old_path = "/foo/bar"
+ new_path = "/mount/bar"
self.filesystem.create_file(old_path)
- self.assert_raises_os_error(errno.EXDEV, self.os.rename, old_path,
- new_path)
+ self.assert_raises_os_error(errno.EXDEV, self.os.rename, old_path, new_path)
def test_rename_to_existent_file_posix(self):
"""Can rename a file to a used name under Unix."""
self.check_posix_only()
- directory = self.make_path('xyzzy')
- old_file_path = self.os.path.join(directory, 'plugh_old')
- new_file_path = self.os.path.join(directory, 'plugh_new')
- self.create_file(old_file_path, contents='test contents 1')
- self.create_file(new_file_path, contents='test contents 2')
+ directory = self.make_path("xyzzy")
+ old_file_path = self.os.path.join(directory, "plugh_old")
+ new_file_path = self.os.path.join(directory, "plugh_new")
+ self.create_file(old_file_path, contents="test contents 1")
+ self.create_file(new_file_path, contents="test contents 2")
self.assertTrue(self.os.path.exists(old_file_path))
self.assertTrue(self.os.path.exists(new_file_path))
self.os.rename(old_file_path, new_file_path)
self.assertFalse(self.os.path.exists(old_file_path))
self.assertTrue(self.os.path.exists(new_file_path))
- self.check_contents(new_file_path, 'test contents 1')
+ self.check_contents(new_file_path, "test contents 1")
def test_rename_to_existent_file_windows(self):
"""Renaming a file to a used name raises OSError under Windows."""
self.check_windows_only()
- directory = self.make_path('xyzzy')
- old_file_path = self.os.path.join(directory, 'plugh_old')
- new_file_path = self.os.path.join(directory, 'plugh_new')
- self.create_file(old_file_path, contents='test contents 1')
- self.create_file(new_file_path, contents='test contents 2')
+ directory = self.make_path("xyzzy")
+ old_file_path = self.os.path.join(directory, "plugh_old")
+ new_file_path = self.os.path.join(directory, "plugh_new")
+ self.create_file(old_file_path, contents="test contents 1")
+ self.create_file(new_file_path, contents="test contents 2")
self.assertTrue(self.os.path.exists(old_file_path))
self.assertTrue(self.os.path.exists(new_file_path))
self.assert_raises_os_error(
- errno.EEXIST, self.os.rename, old_file_path, new_file_path)
+ errno.EEXIST, self.os.rename, old_file_path, new_file_path
+ )
def test_replace_to_existent_file(self):
"""Replaces an existing file (does not work with `rename()` under
Windows)."""
- directory = self.make_path('xyzzy')
- old_file_path = self.os.path.join(directory, 'plugh_old')
- new_file_path = self.os.path.join(directory, 'plugh_new')
- self.create_file(old_file_path, contents='test contents 1')
- self.create_file(new_file_path, contents='test contents 2')
+ directory = self.make_path("xyzzy")
+ old_file_path = self.os.path.join(directory, "plugh_old")
+ new_file_path = self.os.path.join(directory, "plugh_new")
+ self.create_file(old_file_path, contents="test contents 1")
+ self.create_file(new_file_path, contents="test contents 2")
self.assertTrue(self.os.path.exists(old_file_path))
self.assertTrue(self.os.path.exists(new_file_path))
self.os.replace(old_file_path, new_file_path)
self.assertFalse(self.os.path.exists(old_file_path))
self.assertTrue(self.os.path.exists(new_file_path))
- self.check_contents(new_file_path, 'test contents 1')
+ self.check_contents(new_file_path, "test contents 1")
def test_rename_to_nonexistent_dir(self):
"""Can rename a file to a name in a nonexistent dir."""
- directory = self.make_path('xyzzy')
- old_file_path = self.os.path.join(directory, 'plugh_old')
- new_file_path = self.os.path.join(
- directory, 'no_such_path', 'plugh_new')
- self.create_file(old_file_path, contents='test contents')
+ directory = self.make_path("xyzzy")
+ old_file_path = self.os.path.join(directory, "plugh_old")
+ new_file_path = self.os.path.join(directory, "no_such_path", "plugh_new")
+ self.create_file(old_file_path, contents="test contents")
self.assertTrue(self.os.path.exists(old_file_path))
self.assertFalse(self.os.path.exists(new_file_path))
self.assert_raises_os_error(
- errno.ENOENT, self.os.rename, old_file_path, new_file_path)
+ errno.ENOENT, self.os.rename, old_file_path, new_file_path
+ )
self.assertTrue(self.os.path.exists(old_file_path))
self.assertFalse(self.os.path.exists(new_file_path))
- self.check_contents(old_file_path, 'test contents')
+ self.check_contents(old_file_path, "test contents")
def test_rename_nonexistent_file_should_raise_error(self):
"""Can't rename a file that doesn't exist."""
- self.assert_raises_os_error(errno.ENOENT, self.os.rename,
- 'nonexistent-foo', 'doesn\'t-matter-bar')
+ self.assert_raises_os_error(
+ errno.ENOENT,
+ self.os.rename,
+ "nonexistent-foo",
+ "doesn't-matter-bar",
+ )
def test_rename_empty_dir(self):
"""Test a rename of an empty directory."""
- directory = self.make_path('xyzzy')
- before_dir = self.os.path.join(directory, 'empty')
- after_dir = self.os.path.join(directory, 'unused')
+ directory = self.make_path("xyzzy")
+ before_dir = self.os.path.join(directory, "empty")
+ after_dir = self.os.path.join(directory, "unused")
self.create_dir(before_dir)
- self.assertTrue(
- self.os.path.exists(self.os.path.join(before_dir, '.')))
+ self.assertTrue(self.os.path.exists(self.os.path.join(before_dir, ".")))
self.assertFalse(self.os.path.exists(after_dir))
self.os.rename(before_dir, after_dir)
self.assertFalse(self.os.path.exists(before_dir))
- self.assertTrue(self.os.path.exists(self.os.path.join(after_dir, '.')))
+ self.assertTrue(self.os.path.exists(self.os.path.join(after_dir, ".")))
def test_rename_symlink(self):
self.check_posix_only()
- base_path = self.make_path('foo', 'bar')
+ base_path = self.make_path("foo", "bar")
self.create_dir(base_path)
- link_path = self.os.path.join(base_path, 'link')
+ link_path = self.os.path.join(base_path, "link")
self.os.symlink(base_path, link_path)
- file_path = self.os.path.join(link_path, 'file')
- new_file_path = self.os.path.join(link_path, 'new')
+ file_path = self.os.path.join(link_path, "file")
+ new_file_path = self.os.path.join(link_path, "new")
self.create_file(file_path)
self.os.rename(file_path, new_file_path)
self.assertFalse(self.os.path.exists(file_path))
self.assertTrue(self.os.path.exists(new_file_path))
def check_append_mode_tell_after_truncate(self, tell_result):
- file_path = self.make_path('baz')
- with self.open(file_path, 'w') as f0:
- with self.open(file_path, 'a') as f1:
- f1.write('abcde')
+ file_path = self.make_path("baz")
+ with self.open(file_path, "w") as f0:
+ with self.open(file_path, "a") as f1:
+ f1.write("abcde")
f0.seek(2)
f0.truncate()
self.assertEqual(tell_result, f1.tell())
- with self.open(file_path, mode='rb') as f:
- self.assertEqual(b'\0\0abcde', f.read())
+ with self.open(file_path, mode="rb") as f:
+ self.assertEqual(b"\0\0abcde", f.read())
def test_append_mode_tell_linux_windows(self):
# Regression test for #300
@@ -1270,16 +1317,16 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_tell_after_seek_in_append_mode(self):
# Regression test for #363
- file_path = self.make_path('foo')
- with self.open(file_path, 'a') as f:
+ file_path = self.make_path("foo")
+ with self.open(file_path, "a") as f:
f.seek(1)
self.assertEqual(1, f.tell())
def test_tell_after_seekback_in_append_mode(self):
# Regression test for #414
- file_path = self.make_path('foo')
- with self.open(file_path, 'a') as f:
- f.write('aa')
+ file_path = self.make_path("foo")
+ with self.open(file_path, "a") as f:
+ f.write("aa")
f.seek(1)
self.assertEqual(1, f.tell())
@@ -1288,10 +1335,9 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.assertTrue(self, self.os.path.isdir(self.base_path + self.os.sep))
def check_rename_dir_with_trailing_sep(self, error):
- dir_path = self.make_path('dir') + self.os.sep
+ dir_path = self.make_path("dir") + self.os.sep
self.os.mkdir(dir_path)
- self.assert_raises_os_error(error,
- self.os.rename, dir_path, self.base_path)
+ self.assert_raises_os_error(error, self.os.rename, dir_path, self.base_path)
def test_rename_dir_with_trailing_sep_posix(self):
# regression test for #406
@@ -1304,13 +1350,13 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_rename_dir(self):
"""Test a rename of a directory."""
- directory = self.make_path('xyzzy')
- before_dir = self.os.path.join(directory, 'before')
- before_file = self.os.path.join(directory, 'before', 'file')
- after_dir = self.os.path.join(directory, 'after')
- after_file = self.os.path.join(directory, 'after', 'file')
+ directory = self.make_path("xyzzy")
+ before_dir = self.os.path.join(directory, "before")
+ before_file = self.os.path.join(directory, "before", "file")
+ after_dir = self.os.path.join(directory, "after")
+ after_file = self.os.path.join(directory, "after", "file")
self.create_dir(before_dir)
- self.create_file(before_file, contents='payload')
+ self.create_file(before_file, contents="payload")
self.assertTrue(self.os.path.exists(before_dir))
self.assertTrue(self.os.path.exists(before_file))
self.assertFalse(self.os.path.exists(after_dir))
@@ -1320,15 +1366,15 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.assertFalse(self.os.path.exists(before_file))
self.assertTrue(self.os.path.exists(after_dir))
self.assertTrue(self.os.path.exists(after_file))
- self.check_contents(after_file, 'payload')
+ self.check_contents(after_file, "payload")
def test_rename_preserves_stat(self):
"""Test if rename preserves mtime."""
self.check_posix_only()
self.skip_real_fs()
- directory = self.make_path('xyzzy')
- old_file_path = self.os.path.join(directory, 'plugh_old')
- new_file_path = self.os.path.join(directory, 'plugh_new')
+ directory = self.make_path("xyzzy")
+ old_file_path = self.os.path.join(directory, "plugh_old")
+ new_file_path = self.os.path.join(directory, "plugh_new")
self.create_file(old_file_path)
old_file = self.filesystem.get_object(old_file_path)
old_file.st_mtime = old_file.st_mtime - 3600
@@ -1338,8 +1384,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
new_file = self.filesystem.get_object(new_file_path)
self.assertNotEqual(new_file.st_mtime, old_file.st_mtime)
self.os.rename(old_file_path, new_file_path)
- new_file = self.filesystem.get_object(
- new_file_path, check_read_perm=False)
+ new_file = self.filesystem.get_object(new_file_path, check_read_perm=False)
self.assertEqual(new_file.st_mtime, old_file.st_mtime)
self.assertEqual(new_file.st_mode, old_file.st_mode)
self.assertEqual(new_file.st_uid, old_file.st_uid)
@@ -1347,18 +1392,18 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_rename_same_filenames(self):
"""Test renaming when old and new names are the same."""
- directory = self.make_path('xyzzy')
- file_contents = 'Spam eggs'
- file_path = self.os.path.join(directory, 'eggs')
+ directory = self.make_path("xyzzy")
+ file_contents = "Spam eggs"
+ file_path = self.os.path.join(directory, "eggs")
self.create_file(file_path, contents=file_contents)
self.os.rename(file_path, file_path)
self.check_contents(file_path, file_contents)
def test_rmdir(self):
"""Can remove a directory."""
- directory = self.make_path('xyzzy')
- sub_dir = self.make_path('xyzzy', 'abccd')
- other_dir = self.make_path('xyzzy', 'cdeed')
+ directory = self.make_path("xyzzy")
+ sub_dir = self.make_path("xyzzy", "abccd")
+ other_dir = self.make_path("xyzzy", "cdeed")
self.create_dir(directory)
self.assertTrue(self.os.path.exists(directory))
self.os.rmdir(directory)
@@ -1366,28 +1411,28 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.create_dir(sub_dir)
self.create_dir(other_dir)
self.os.chdir(sub_dir)
- self.os.rmdir('../cdeed')
+ self.os.rmdir("../cdeed")
self.assertFalse(self.os.path.exists(other_dir))
- self.os.chdir('..')
- self.os.rmdir('abccd')
+ self.os.chdir("..")
+ self.os.rmdir("abccd")
self.assertFalse(self.os.path.exists(sub_dir))
def test_rmdir_raises_if_not_empty(self):
"""Raises an exception if the target directory is not empty."""
- directory = self.make_path('xyzzy')
- file_path = self.os.path.join(directory, 'plugh')
+ directory = self.make_path("xyzzy")
+ file_path = self.os.path.join(directory, "plugh")
self.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path))
self.assert_raises_os_error(errno.ENOTEMPTY, self.os.rmdir, directory)
def check_rmdir_raises_if_not_directory(self, error_nr):
"""Raises an exception if the target is not a directory."""
- directory = self.make_path('xyzzy')
- file_path = self.os.path.join(directory, 'plugh')
+ directory = self.make_path("xyzzy")
+ file_path = self.os.path.join(directory, "plugh")
self.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path))
self.assert_raises_os_error(errno.ENOTDIR, self.os.rmdir, file_path)
- self.assert_raises_os_error(error_nr, self.os.rmdir, '.')
+ self.assert_raises_os_error(error_nr, self.os.rmdir, ".")
def test_rmdir_raises_if_not_directory_posix(self):
self.check_posix_only()
@@ -1399,19 +1444,19 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_rmdir_raises_if_not_exist(self):
"""Raises an exception if the target does not exist."""
- directory = self.make_path('xyzzy')
+ directory = self.make_path("xyzzy")
self.assertFalse(self.os.path.exists(directory))
self.assert_raises_os_error(errno.ENOENT, self.os.rmdir, directory)
def test_rmdir_via_symlink(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- base_path = self.make_path('foo', 'bar')
- dir_path = self.os.path.join(base_path, 'alpha')
+ base_path = self.make_path("foo", "bar")
+ dir_path = self.os.path.join(base_path, "alpha")
self.create_dir(dir_path)
- link_path = self.os.path.join(base_path, 'beta')
+ link_path = self.os.path.join(base_path, "beta")
self.os.symlink(base_path, link_path)
- self.os.rmdir(link_path + '/alpha')
+ self.os.rmdir(link_path + "/alpha")
self.assertFalse(self.os.path.exists(dir_path))
def remove_dirs_check(self, directory):
@@ -1422,15 +1467,21 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_removedirs(self):
# no exception raised
self.skip_real_fs()
- data = ['test1', ('test1', 'test2'), ('test1', 'extra'),
- ('test1', 'test2', 'test3')]
+ data = [
+ "test1",
+ ("test1", "test2"),
+ ("test1", "extra"),
+ ("test1", "test2", "test3"),
+ ]
for directory in data:
self.create_dir(self.make_path(directory))
self.assertTrue(self.os.path.exists(self.make_path(directory)))
- self.assert_raises_os_error(errno.ENOTEMPTY, self.remove_dirs_check,
- self.make_path(data[0]))
- self.assert_raises_os_error(errno.ENOTEMPTY, self.remove_dirs_check,
- self.make_path(data[1]))
+ self.assert_raises_os_error(
+ errno.ENOTEMPTY, self.remove_dirs_check, self.make_path(data[0])
+ )
+ self.assert_raises_os_error(
+ errno.ENOTEMPTY, self.remove_dirs_check, self.make_path(data[1])
+ )
self.assertTrue(self.remove_dirs_check(self.make_path(data[3])))
self.assertTrue(self.os.path.exists(self.make_path(data[0])))
@@ -1439,26 +1490,25 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
# Should raise because '/test1/extra' is all that is left, and
# removedirs('/test1/extra') will eventually try to rmdir('/').
- self.assert_raises_os_error(errno.EBUSY, self.remove_dirs_check,
- self.make_path(data[2]))
+ self.assert_raises_os_error(
+ errno.EBUSY, self.remove_dirs_check, self.make_path(data[2])
+ )
# However, it will still delete '/test1') in the process.
self.assertFalse(self.os.path.exists(self.make_path(data[0])))
- self.create_dir(self.make_path('test1', 'test2'))
+ self.create_dir(self.make_path("test1", "test2"))
# Add this to the root directory to avoid raising an exception.
- self.filesystem.create_dir(self.make_path('test3'))
- self.assertTrue(
- self.remove_dirs_check(self.make_path('test1', 'test2')))
- self.assertFalse(self.os.path.exists(self.make_path('test1', 'test2')))
- self.assertFalse(self.os.path.exists(self.make_path('test1')))
+ self.filesystem.create_dir(self.make_path("test3"))
+ self.assertTrue(self.remove_dirs_check(self.make_path("test1", "test2")))
+ self.assertFalse(self.os.path.exists(self.make_path("test1", "test2")))
+ self.assertFalse(self.os.path.exists(self.make_path("test1")))
def test_removedirs_raises_if_removing_root(self):
"""Raises exception if asked to remove '/'."""
self.skip_real_fs()
self.os.rmdir(self.base_path)
- directory = self.os.path.splitdrive(
- self.base_path)[0] + self.os.path.sep
+ directory = self.os.path.splitdrive(self.base_path)[0] + self.os.path.sep
self.assertTrue(self.os.path.exists(directory))
self.assert_raises_os_error(errno.EBUSY, self.os.removedirs, directory)
@@ -1469,7 +1519,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
All of other directories should still be removed, though.
"""
self.skip_real_fs()
- directory = self.make_path('foo', 'bar')
+ directory = self.make_path("foo", "bar")
self.create_dir(directory)
self.assertTrue(self.os.path.exists(directory))
self.assert_raises_os_error(errno.EBUSY, self.os.removedirs, directory)
@@ -1481,8 +1531,8 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_removedirs_with_trailing_slash(self):
"""removedirs works on directory names with trailing slashes."""
# separate this case from the removing-root-directory case
- self.create_dir(self.make_path('baz'))
- directory = self.make_path('foo', 'bar')
+ self.create_dir(self.make_path("baz"))
+ directory = self.make_path("foo", "bar")
self.create_dir(directory)
self.assertTrue(self.os.path.exists(directory))
self.os.removedirs(directory)
@@ -1490,20 +1540,19 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_remove_dirs_with_top_symlink_fails(self):
self.check_posix_only()
- dir_path = self.make_path('dir')
- dir_link = self.make_path('dir_link')
+ dir_path = self.make_path("dir")
+ dir_link = self.make_path("dir_link")
self.create_dir(dir_path)
self.os.symlink(dir_path, dir_link)
- self.assert_raises_os_error(errno.ENOTDIR,
- self.os.removedirs, dir_link)
+ self.assert_raises_os_error(errno.ENOTDIR, self.os.removedirs, dir_link)
def test_remove_dirs_with_non_top_symlink_succeeds(self):
self.check_posix_only()
- dir_path = self.make_path('dir')
- dir_link = self.make_path('dir_link')
+ dir_path = self.make_path("dir")
+ dir_link = self.make_path("dir_link")
self.create_dir(dir_path)
self.os.symlink(dir_path, dir_link)
- dir_in_dir = self.os.path.join(dir_link, 'dir2')
+ dir_in_dir = self.os.path.join(dir_link, "dir2")
self.create_dir(dir_in_dir)
self.os.removedirs(dir_in_dir)
self.assertFalse(self.os.path.exists(dir_in_dir))
@@ -1513,43 +1562,42 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_mkdir(self):
"""mkdir can create a relative directory."""
self.skip_real_fs()
- directory = 'xyzzy'
+ directory = "xyzzy"
self.assertFalse(self.filesystem.exists(directory))
self.os.mkdir(directory)
- self.assertTrue(self.filesystem.exists('/%s' % directory))
+ self.assertTrue(self.filesystem.exists("/%s" % directory))
self.os.chdir(directory)
self.os.mkdir(directory)
- self.assertTrue(
- self.filesystem.exists('/%s/%s' % (directory, directory)))
+ self.assertTrue(self.filesystem.exists("/%s/%s" % (directory, directory)))
self.os.chdir(directory)
- self.os.mkdir('../abccb')
- self.assertTrue(self.os.path.exists('/%s/abccb' % directory))
+ self.os.mkdir("../abccb")
+ self.assertTrue(self.os.path.exists("/%s/abccb" % directory))
def test_mkdir_with_trailing_slash(self):
"""mkdir can create a directory named with a trailing slash."""
- directory = self.make_path('foo')
+ directory = self.make_path("foo")
self.assertFalse(self.os.path.exists(directory))
self.os.mkdir(directory)
self.assertTrue(self.os.path.exists(directory))
- self.assertTrue(self.os.path.exists(self.make_path('foo')))
+ self.assertTrue(self.os.path.exists(self.make_path("foo")))
def test_mkdir_raises_if_empty_directory_name(self):
- """mkdir raises exeption if creating directory named ''."""
- directory = ''
+ """mkdir raises exception if creating directory named ''."""
+ directory = ""
self.assert_raises_os_error(errno.ENOENT, self.os.mkdir, directory)
def test_mkdir_raises_if_no_parent(self):
"""mkdir raises exception if parent directory does not exist."""
- parent = 'xyzzy'
- directory = '%s/foo' % (parent,)
+ parent = "xyzzy"
+ directory = "%s/foo" % (parent,)
self.assertFalse(self.os.path.exists(parent))
self.assert_raises_os_error(errno.ENOENT, self.os.mkdir, directory)
def test_mkdir_raises_on_symlink_in_posix(self):
self.check_posix_only()
- base_path = self.make_path('foo', 'bar')
- link_path = self.os.path.join(base_path, 'link_to_dir')
- dir_path = self.os.path.join(base_path, 'dir')
+ base_path = self.make_path("foo", "bar")
+ link_path = self.os.path.join(base_path, "link_to_dir")
+ dir_path = self.os.path.join(base_path, "dir")
self.create_dir(dir_path)
self.os.symlink(dir_path, link_path)
self.assert_raises_os_error(errno.ENOTDIR, self.os.rmdir, link_path)
@@ -1557,9 +1605,9 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_mkdir_removes_symlink_in_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- base_path = self.make_path('foo', 'bar')
- link_path = self.os.path.join(base_path, 'link_to_dir')
- dir_path = self.os.path.join(base_path, 'dir')
+ base_path = self.make_path("foo", "bar")
+ link_path = self.os.path.join(base_path, "link_to_dir")
+ dir_path = self.os.path.join(base_path, "dir")
self.create_dir(dir_path)
self.os.symlink(dir_path, link_path)
self.os.rmdir(link_path)
@@ -1568,26 +1616,27 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_mkdir_raises_if_directory_exists(self):
"""mkdir raises exception if directory already exists."""
- directory = self.make_path('xyzzy')
+ directory = self.make_path("xyzzy")
self.create_dir(directory)
self.assertTrue(self.os.path.exists(directory))
self.assert_raises_os_error(errno.EEXIST, self.os.mkdir, directory)
def test_mkdir_raises_if_file_exists(self):
"""mkdir raises exception if name already exists as a file."""
- directory = self.make_path('xyzzy')
- file_path = self.os.path.join(directory, 'plugh')
+ directory = self.make_path("xyzzy")
+ file_path = self.os.path.join(directory, "plugh")
self.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path))
self.assert_raises_os_error(errno.EEXIST, self.os.mkdir, file_path)
def check_mkdir_raises_if_parent_is_file(self, error_type):
"""mkdir raises exception if name already exists as a file."""
- directory = self.make_path('xyzzy')
- file_path = self.os.path.join(directory, 'plugh')
+ directory = self.make_path("xyzzy")
+ file_path = self.os.path.join(directory, "plugh")
self.create_file(file_path)
- self.assert_raises_os_error(error_type, self.os.mkdir,
- self.os.path.join(file_path, 'ff'))
+ self.assert_raises_os_error(
+ error_type, self.os.mkdir, self.os.path.join(file_path, "ff")
+ )
def test_mkdir_raises_if_parent_is_file_posix(self):
self.check_posix_only()
@@ -1600,64 +1649,59 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_mkdir_raises_with_slash_dot_posix(self):
"""mkdir raises exception if mkdir foo/. (trailing /.)."""
self.check_posix_only()
- self.assert_raises_os_error(errno.EEXIST,
- self.os.mkdir, self.os.sep + '.')
- directory = self.make_path('xyzzy', '.')
+ self.assert_raises_os_error(errno.EEXIST, self.os.mkdir, self.os.sep + ".")
+ directory = self.make_path("xyzzy", ".")
self.assert_raises_os_error(errno.ENOENT, self.os.mkdir, directory)
- self.create_dir(self.make_path('xyzzy'))
+ self.create_dir(self.make_path("xyzzy"))
self.assert_raises_os_error(errno.EEXIST, self.os.mkdir, directory)
def test_mkdir_raises_with_slash_dot_windows(self):
"""mkdir raises exception if mkdir foo/. (trailing /.)."""
self.check_windows_only()
- self.assert_raises_os_error(errno.EACCES,
- self.os.mkdir, self.os.sep + '.')
- directory = self.make_path('xyzzy', '.')
+ self.assert_raises_os_error(errno.EACCES, self.os.mkdir, self.os.sep + ".")
+ directory = self.make_path("xyzzy", ".")
self.os.mkdir(directory)
- self.create_dir(self.make_path('xyzzy'))
+ self.create_dir(self.make_path("xyzzy"))
self.assert_raises_os_error(errno.EEXIST, self.os.mkdir, directory)
def test_mkdir_raises_with_double_dots_posix(self):
"""mkdir raises exception if mkdir foo/foo2/../foo3."""
self.check_posix_only()
- self.assert_raises_os_error(errno.EEXIST,
- self.os.mkdir, self.os.sep + '..')
- directory = self.make_path('xyzzy', 'dir1', 'dir2', '..', '..', 'dir3')
+ self.assert_raises_os_error(errno.EEXIST, self.os.mkdir, self.os.sep + "..")
+ directory = self.make_path("xyzzy", "dir1", "dir2", "..", "..", "dir3")
self.assert_raises_os_error(errno.ENOENT, self.os.mkdir, directory)
- self.create_dir(self.make_path('xyzzy'))
+ self.create_dir(self.make_path("xyzzy"))
self.assert_raises_os_error(errno.ENOENT, self.os.mkdir, directory)
- self.create_dir(self.make_path('xyzzy', 'dir1'))
+ self.create_dir(self.make_path("xyzzy", "dir1"))
self.assert_raises_os_error(errno.ENOENT, self.os.mkdir, directory)
- self.create_dir(self.make_path('xyzzy', 'dir1', 'dir2'))
+ self.create_dir(self.make_path("xyzzy", "dir1", "dir2"))
self.os.mkdir(directory)
self.assertTrue(self.os.path.exists(directory))
- directory = self.make_path('xyzzy', 'dir1', '..')
+ directory = self.make_path("xyzzy", "dir1", "..")
self.assert_raises_os_error(errno.EEXIST, self.os.mkdir, directory)
def test_mkdir_raises_with_double_dots_windows(self):
"""mkdir raises exception if mkdir foo/foo2/../foo3."""
self.check_windows_only()
- self.assert_raises_os_error(errno.EACCES,
- self.os.mkdir, self.os.sep + '..')
- directory = self.make_path(
- 'xyzzy', 'dir1', 'dir2', '..', '..', 'dir3')
+ self.assert_raises_os_error(errno.EACCES, self.os.mkdir, self.os.sep + "..")
+ directory = self.make_path("xyzzy", "dir1", "dir2", "..", "..", "dir3")
self.assert_raises_os_error(errno.ENOENT, self.os.mkdir, directory)
- self.create_dir(self.make_path('xyzzy'))
+ self.create_dir(self.make_path("xyzzy"))
self.os.mkdir(directory)
self.assertTrue(self.os.path.exists(directory))
- directory = self.make_path('xyzzy', 'dir1', '..')
+ directory = self.make_path("xyzzy", "dir1", "..")
self.assert_raises_os_error(errno.EEXIST, self.os.mkdir, directory)
def test_mkdir_raises_if_parent_is_read_only(self):
"""mkdir raises exception if parent is read only."""
self.check_posix_only()
- directory = self.make_path('a')
+ directory = self.make_path("a")
self.os.mkdir(directory)
# Change directory permissions to be read only.
self.os.chmod(directory, 0o400)
- directory = self.make_path('a', 'b')
+ directory = self.make_path("a", "b")
if not is_root():
self.assert_raises_os_error(errno.EACCES, self.os.mkdir, directory)
else:
@@ -1666,26 +1710,26 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_mkdir_with_with_symlink_parent(self):
self.check_posix_only()
- dir_path = self.make_path('foo', 'bar')
+ dir_path = self.make_path("foo", "bar")
self.create_dir(dir_path)
- link_path = self.make_path('foo', 'link')
+ link_path = self.make_path("foo", "link")
self.os.symlink(dir_path, link_path)
- new_dir = self.os.path.join(link_path, 'new_dir')
+ new_dir = self.os.path.join(link_path, "new_dir")
self.os.mkdir(new_dir)
self.assertTrue(self.os.path.exists(new_dir))
def test_makedirs(self):
"""makedirs can create a directory even if parent does not exist."""
- parent = self.make_path('xyzzy')
- directory = self.os.path.join(parent, 'foo')
+ parent = self.make_path("xyzzy")
+ directory = self.os.path.join(parent, "foo")
self.assertFalse(self.os.path.exists(parent))
self.os.makedirs(directory)
self.assertTrue(self.os.path.exists(directory))
def check_makedirs_raises_if_parent_is_file(self, error_type):
"""makedirs raises exception if a parent component exists as a file."""
- file_path = self.make_path('xyzzy')
- directory = self.os.path.join(file_path, 'plugh')
+ file_path = self.make_path("xyzzy")
+ directory = self.os.path.join(file_path, "plugh")
self.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path))
self.assert_raises_os_error(error_type, self.os.makedirs, directory)
@@ -1700,40 +1744,43 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_makedirs_raises_if_parent_is_broken_link(self):
self.check_posix_only()
- link_path = self.make_path('broken_link')
- self.os.symlink(self.make_path('bogus'), link_path)
- self.assert_raises_os_error(errno.ENOENT, self.os.makedirs,
- self.os.path.join(link_path, 'newdir'))
+ link_path = self.make_path("broken_link")
+ self.os.symlink(self.make_path("bogus"), link_path)
+ self.assert_raises_os_error(
+ errno.ENOENT,
+ self.os.makedirs,
+ self.os.path.join(link_path, "newdir"),
+ )
def test_makedirs_raises_if_parent_is_looping_link(self):
self.skip_if_symlink_not_supported()
- link_path = self.make_path('link')
- link_target = self.os.path.join(link_path, 'link')
+ link_path = self.make_path("link")
+ link_target = self.os.path.join(link_path, "link")
self.os.symlink(link_target, link_path)
self.assert_raises_os_error(errno.EEXIST, self.os.makedirs, link_path)
def test_makedirs_if_parent_is_symlink(self):
self.check_posix_only()
- base_dir = self.make_path('foo', 'bar')
+ base_dir = self.make_path("foo", "bar")
self.create_dir(base_dir)
- link_dir = self.os.path.join(base_dir, 'linked')
+ link_dir = self.os.path.join(base_dir, "linked")
self.os.symlink(base_dir, link_dir)
- new_dir = self.os.path.join(link_dir, 'f')
+ new_dir = self.os.path.join(link_dir, "f")
self.os.makedirs(name=new_dir)
self.assertTrue(self.os.path.exists(new_dir))
def test_makedirs_raises_if_access_denied(self):
"""makedirs raises exception if access denied."""
self.check_posix_only()
- directory = self.make_path('a')
+ directory = self.make_path("a")
self.os.mkdir(directory)
# Change directory permissions to be read only.
self.os.chmod(directory, 0o400)
- directory = self.make_path('a', 'b')
+ directory = self.make_path("a", "b")
if not is_root():
- with self.assertRaises(Exception):
+ with self.assertRaises(OSError):
self.os.makedirs(directory)
else:
self.os.makedirs(directory)
@@ -1741,7 +1788,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_makedirs_exist_ok(self):
"""makedirs uses the exist_ok argument"""
- directory = self.make_path('xyzzy', 'foo')
+ directory = self.make_path("xyzzy", "foo")
self.create_dir(directory)
self.assertTrue(self.os.path.exists(directory))
@@ -1751,23 +1798,23 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_makedirs_in_write_protected_dir(self):
self.check_posix_only()
- directory = self.make_path('foo')
+ directory = self.make_path("foo")
self.os.mkdir(directory, mode=0o555)
- subdir = self.os.path.join(directory, 'bar')
+ subdir = self.os.path.join(directory, "bar")
if not is_root():
- self.assert_raises_os_error(errno.EACCES, self.os.makedirs,
- subdir, exist_ok=True)
- self.assert_raises_os_error(errno.EACCES, self.os.makedirs,
- subdir, exist_ok=False)
+ self.assert_raises_os_error(
+ errno.EACCES, self.os.makedirs, subdir, exist_ok=True
+ )
+ self.assert_raises_os_error(
+ errno.EACCES, self.os.makedirs, subdir, exist_ok=False
+ )
else:
self.os.makedirs(subdir)
self.assertTrue(self.os.path.exists(subdir))
def test_makedirs_raises_on_empty_path(self):
- self.assert_raises_os_error(
- errno.ENOENT, self.os.makedirs, '', exist_ok=False)
- self.assert_raises_os_error(
- errno.ENOENT, self.os.makedirs, '', exist_ok=True)
+ self.assert_raises_os_error(errno.ENOENT, self.os.makedirs, "", exist_ok=False)
+ self.assert_raises_os_error(errno.ENOENT, self.os.makedirs, "", exist_ok=True)
# test fsync and fdatasync
def test_fsync_raises_on_non_int(self):
@@ -1789,48 +1836,45 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_fsync_pass_posix(self):
self.check_posix_only()
- test_file_path = self.make_path('test_file')
- self.create_file(test_file_path, contents='dummy file contents')
- with self.open(test_file_path, 'r') as test_file:
+ test_file_path = self.make_path("test_file")
+ self.create_file(test_file_path, contents="dummy file contents")
+ with self.open(test_file_path, "r") as test_file:
test_fd = test_file.fileno()
# Test that this doesn't raise anything
self.os.fsync(test_fd)
# And just for sanity, double-check that this still raises
- self.assert_raises_os_error(errno.EBADF,
- self.os.fsync, test_fd + 500)
+ self.assert_raises_os_error(errno.EBADF, self.os.fsync, test_fd + 500)
def test_fsync_pass_windows(self):
self.check_windows_only()
- test_file_path = self.make_path('test_file')
- self.create_file(test_file_path, contents='dummy file contents')
- with self.open(test_file_path, 'r+') as test_file:
+ test_file_path = self.make_path("test_file")
+ self.create_file(test_file_path, contents="dummy file contents")
+ with self.open(test_file_path, "r+") as test_file:
test_fd = test_file.fileno()
# Test that this doesn't raise anything
self.os.fsync(test_fd)
# And just for sanity, double-check that this still raises
- self.assert_raises_os_error(errno.EBADF,
- self.os.fsync, test_fd + 500)
- with self.open(test_file_path, 'r') as test_file:
+ self.assert_raises_os_error(errno.EBADF, self.os.fsync, test_fd + 500)
+ with self.open(test_file_path, "r") as test_file:
test_fd = test_file.fileno()
self.assert_raises_os_error(errno.EBADF, self.os.fsync, test_fd)
def test_fdatasync_pass(self):
# setup
self.check_linux_only()
- test_file_path = self.make_path('test_file')
- self.create_file(test_file_path, contents='dummy file contents')
- test_file = self.open(test_file_path, 'r')
+ test_file_path = self.make_path("test_file")
+ self.create_file(test_file_path, contents="dummy file contents")
+ test_file = self.open(test_file_path, "r")
test_fd = test_file.fileno()
# Test that this doesn't raise anything
self.os.fdatasync(test_fd)
# And just for sanity, double-check that this still raises
- self.assert_raises_os_error(errno.EBADF,
- self.os.fdatasync, test_fd + 500)
+ self.assert_raises_os_error(errno.EBADF, self.os.fdatasync, test_fd + 500)
def test_access700(self):
# set up
self.check_posix_only()
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
self.os.chmod(path, 0o700)
self.assert_mode_equal(0o700, self.os.stat(path).st_mode)
@@ -1844,7 +1888,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_access600(self):
# set up
self.check_posix_only()
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
self.os.chmod(path, 0o600)
self.assert_mode_equal(0o600, self.os.stat(path).st_mode)
@@ -1859,7 +1903,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_access400(self):
# set up
self.check_posix_only()
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
self.os.chmod(path, 0o400)
self.assert_mode_equal(0o400, self.os.stat(path).st_mode)
@@ -1878,9 +1922,9 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_access_symlink(self):
self.skip_if_symlink_not_supported()
self.skip_real_fs()
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
- link_path = self.make_path('link_to_some_file')
+ link_path = self.make_path("link_to_some_file")
self.create_symlink(link_path, path)
self.os.chmod(link_path, 0o400)
@@ -1897,22 +1941,16 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.assertFalse(self.os.access(link_path, self.rwx))
# test link itself
- self.assertTrue(
- self.os.access(link_path, self.os.F_OK, follow_symlinks=False))
- self.assertTrue(
- self.os.access(link_path, self.os.R_OK, follow_symlinks=False))
- self.assertTrue(
- self.os.access(link_path, self.os.W_OK, follow_symlinks=False))
- self.assertTrue(
- self.os.access(link_path, self.os.X_OK, follow_symlinks=False))
- self.assertTrue(
- self.os.access(link_path, self.rwx, follow_symlinks=False))
- self.assertTrue(
- self.os.access(link_path, self.rw, follow_symlinks=False))
+ self.assertTrue(self.os.access(link_path, self.os.F_OK, follow_symlinks=False))
+ self.assertTrue(self.os.access(link_path, self.os.R_OK, follow_symlinks=False))
+ self.assertTrue(self.os.access(link_path, self.os.W_OK, follow_symlinks=False))
+ self.assertTrue(self.os.access(link_path, self.os.X_OK, follow_symlinks=False))
+ self.assertTrue(self.os.access(link_path, self.rwx, follow_symlinks=False))
+ self.assertTrue(self.os.access(link_path, self.rw, follow_symlinks=False))
def test_access_non_existent_file(self):
# set up
- path = self.make_path('non', 'existent', 'file')
+ path = self.make_path("non", "existent", "file")
self.assertFalse(self.os.path.exists(path))
# actual tests
self.assertFalse(self.os.access(path, self.os.F_OK))
@@ -1924,7 +1962,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_effective_ids_not_supported_under_windows(self):
self.check_windows_only()
- path = self.make_path('foo', 'bar')
+ path = self.make_path("foo", "bar")
with self.assertRaises(NotImplementedError):
self.os.access(path, self.os.F_OK, effective_ids=True)
@@ -1932,7 +1970,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
# set up
self.check_posix_only()
self.skip_real_fs()
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
# actual tests
self.os.chmod(path, 0o6543)
@@ -1945,7 +1983,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.check_posix_only()
self.skip_real_fs()
self.assert_raises_os_error(errno.EBADF, self.os.chmod, 5, 0o6543)
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
with self.open(path) as f:
@@ -1955,9 +1993,9 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_chmod_follow_symlink(self):
self.check_posix_only()
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
- link_path = self.make_path('link_to_some_file')
+ link_path = self.make_path("link_to_some_file")
self.create_symlink(link_path, path)
self.os.chmod(link_path, 0o6543)
@@ -1969,11 +2007,11 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_chmod_no_follow_symlink(self):
self.check_posix_only()
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
- link_path = self.make_path('link_to_some_file')
+ link_path = self.make_path("link_to_some_file")
self.create_symlink(link_path, path)
- if os.chmod not in os.supports_follow_symlinks or IS_PYPY:
+ if self.os.chmod not in self.os.supports_follow_symlinks or IS_PYPY:
with self.assertRaises(NotImplementedError):
self.os.chmod(link_path, 0o6543, follow_symlinks=False)
else:
@@ -1987,9 +2025,9 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
"""lchmod shall behave like chmod with follow_symlinks=True."""
self.check_posix_only()
self.skip_real_fs()
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
- link_path = self.make_path('link_to_some_file')
+ link_path = self.make_path("link_to_some_file")
self.create_symlink(link_path, path)
self.os.lchmod(link_path, 0o6543)
@@ -2002,7 +2040,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
# set up
self.check_posix_only()
self.skip_real_fs()
- path = self.make_path('some_dir')
+ path = self.make_path("some_dir")
self.createTestDirectory(path)
# actual tests
self.os.chmod(path, 0o1434)
@@ -2013,13 +2051,13 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_chmod_non_existent(self):
# set up
- path = self.make_path('non', 'existent', 'file')
+ path = self.make_path("non", "existent", "file")
self.assertFalse(self.os.path.exists(path))
# actual tests
try:
# Use try-catch to check exception attributes.
self.os.chmod(path, 0o777)
- self.fail('Exception is expected.') # COV_NF_LINE
+ self.fail("Exception is expected.") # COV_NF_LINE
except OSError as os_error:
self.assertEqual(errno.ENOENT, os_error.errno)
self.assertEqual(path, os_error.filename)
@@ -2027,7 +2065,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_chown_existing_file(self):
# set up
self.skip_real_fs()
- file_path = self.make_path('some_file')
+ file_path = self.make_path("some_file")
self.create_file(file_path)
# first set it make sure it's set
self.os.chown(file_path, 100, 101)
@@ -2049,7 +2087,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.check_posix_only()
self.skip_real_fs()
self.assert_raises_os_error(errno.EBADF, self.os.chown, 5, 100, 101)
- file_path = self.make_path('foo', 'bar')
+ file_path = self.make_path("foo", "bar")
self.create_file(file_path)
with self.open(file_path) as f:
@@ -2059,9 +2097,9 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_chown_follow_symlink(self):
self.skip_real_fs()
- file_path = self.make_path('some_file')
+ file_path = self.make_path("some_file")
self.create_file(file_path)
- link_path = self.make_path('link_to_some_file')
+ link_path = self.make_path("link_to_some_file")
self.create_symlink(link_path, file_path)
self.os.chown(link_path, 100, 101)
@@ -2074,9 +2112,9 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_chown_no_follow_symlink(self):
self.skip_real_fs()
- file_path = self.make_path('some_file')
+ file_path = self.make_path("some_file")
self.create_file(file_path)
- link_path = self.make_path('link_to_some_file')
+ link_path = self.make_path("link_to_some_file")
self.create_symlink(link_path, file_path)
self.os.chown(link_path, 100, 101, follow_symlinks=False)
@@ -2090,23 +2128,22 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_chown_bad_arguments(self):
"""os.chown() with bad args (Issue #30)"""
self.check_posix_only()
- file_path = self.make_path('some_file')
+ file_path = self.make_path("some_file")
self.create_file(file_path)
- self.assertRaises(TypeError, self.os.chown, file_path, 'username', -1)
- self.assertRaises(TypeError, self.os.chown, file_path, -1, 'groupname')
+ self.assertRaises(TypeError, self.os.chown, file_path, "username", -1)
+ self.assertRaises(TypeError, self.os.chown, file_path, -1, "groupname")
def test_chown_nonexisting_file_should_raise_os_error(self):
self.check_posix_only()
- file_path = self.make_path('some_file')
+ file_path = self.make_path("some_file")
self.assertFalse(self.os.path.exists(file_path))
- self.assert_raises_os_error(
- errno.ENOENT, self.os.chown, file_path, 100, 100)
+ self.assert_raises_os_error(errno.ENOENT, self.os.chown, file_path, 100, 100)
def test_classify_directory_contents(self):
"""Directory classification should work correctly."""
- root_directory = self.make_path('foo')
- test_directories = ['bar1', 'baz2']
- test_files = ['baz1', 'bar2', 'baz3']
+ root_directory = self.make_path("foo")
+ test_directories = ["bar1", "baz2"]
+ test_files = ["baz1", "bar2", "baz3"]
self.create_dir(root_directory)
for directory in test_directories:
directory = self.os.path.join(root_directory, directory)
@@ -2129,7 +2166,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
# so we test it under Linux only
def test_mk_nod_can_create_a_file(self):
self.check_linux_only()
- filename = self.make_path('foo')
+ filename = self.make_path("foo")
self.assertFalse(self.os.path.exists(filename))
self.os.mknod(filename)
self.assertTrue(self.os.path.exists(filename))
@@ -2137,48 +2174,48 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_mk_nod_raises_if_empty_file_name(self):
self.check_linux_only()
- filename = ''
+ filename = ""
self.assert_raises_os_error(errno.ENOENT, self.os.mknod, filename)
def test_mk_nod_raises_if_parent_dir_doesnt_exist(self):
self.check_linux_only()
- parent = self.make_path('xyzzy')
- filename = self.os.path.join(parent, 'foo')
+ parent = self.make_path("xyzzy")
+ filename = self.os.path.join(parent, "foo")
self.assertFalse(self.os.path.exists(parent))
self.assert_raises_os_error(errno.ENOENT, self.os.mknod, filename)
def test_mk_nod_raises_if_file_exists(self):
self.check_linux_only()
- filename = self.make_path('tmp', 'foo')
+ filename = self.make_path("tmp", "foo")
self.create_file(filename)
self.assertTrue(self.os.path.exists(filename))
self.assert_raises_os_error(errno.EEXIST, self.os.mknod, filename)
def test_mk_nod_raises_if_filename_is_dot(self):
self.check_linux_only()
- filename = self.make_path('tmp', '.')
+ filename = self.make_path("tmp", ".")
self.assert_raises_os_error(errno.ENOENT, self.os.mknod, filename)
def test_mk_nod_raises_if_filename_is_double_dot(self):
self.check_linux_only()
- filename = self.make_path('tmp', '..')
+ filename = self.make_path("tmp", "..")
self.assert_raises_os_error(errno.ENOENT, self.os.mknod, filename)
def test_mknod_empty_tail_for_existing_file_raises(self):
self.check_linux_only()
- filename = self.make_path('foo')
+ filename = self.make_path("foo")
self.create_file(filename)
self.assertTrue(self.os.path.exists(filename))
self.assert_raises_os_error(errno.EEXIST, self.os.mknod, filename)
def test_mknod_empty_tail_for_nonexistent_file_raises(self):
self.check_linux_only()
- filename = self.make_path('tmp', 'foo')
+ filename = self.make_path("tmp", "foo")
self.assert_raises_os_error(errno.ENOENT, self.os.mknod, filename)
def test_mknod_raises_if_filename_is_empty_string(self):
self.check_linux_only()
- filename = ''
+ filename = ""
self.assert_raises_os_error(errno.ENOENT, self.os.mknod, filename)
def test_mknod_raises_if_unsupported_options(self):
@@ -2186,119 +2223,129 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
# behavior seems to have changed in ubuntu-20.04, version 20210606.1
# skipping real fs tests for now
self.skip_real_fs()
- filename = 'abcde'
+ filename = "abcde"
if not is_root():
- self.assert_raises_os_error(errno.EPERM, self.os.mknod, filename,
- stat.S_IFCHR)
+ self.assert_raises_os_error(
+ errno.EPERM, self.os.mknod, filename, stat.S_IFCHR
+ )
else:
self.os.mknod(filename, stat.S_IFCHR)
self.os.remove(filename)
def test_mknod_raises_if_parent_is_not_a_directory(self):
self.check_linux_only()
- filename1 = self.make_path('foo')
+ filename1 = self.make_path("foo")
self.create_file(filename1)
self.assertTrue(self.os.path.exists(filename1))
- filename2 = self.make_path('foo', 'bar')
+ filename2 = self.make_path("foo", "bar")
self.assert_raises_os_error(errno.ENOTDIR, self.os.mknod, filename2)
def test_symlink(self):
self.skip_if_symlink_not_supported()
- file_path = self.make_path('foo', 'bar', 'baz')
- self.create_dir(self.make_path('foo', 'bar'))
- self.os.symlink('bogus', file_path)
+ file_path = self.make_path("foo", "bar", "baz")
+ self.create_dir(self.make_path("foo", "bar"))
+ self.os.symlink("bogus", file_path)
self.assertTrue(self.os.path.lexists(file_path))
self.assertFalse(self.os.path.exists(file_path))
- self.create_file(self.make_path('foo', 'bar', 'bogus'))
+ self.create_file(self.make_path("foo", "bar", "bogus"))
self.assertTrue(self.os.path.lexists(file_path))
self.assertTrue(self.os.path.exists(file_path))
def test_symlink_on_nonexisting_path_raises(self):
self.check_posix_only()
- dir_path = self.make_path('bar')
- link_path = self.os.path.join(dir_path, 'bar')
- self.assert_raises_os_error(errno.ENOENT, self.os.symlink, link_path,
- link_path)
- self.assert_raises_os_error(errno.ENOENT, self.os.symlink, dir_path,
- link_path)
+ dir_path = self.make_path("bar")
+ link_path = self.os.path.join(dir_path, "bar")
+ self.assert_raises_os_error(errno.ENOENT, self.os.symlink, link_path, link_path)
+ self.assert_raises_os_error(errno.ENOENT, self.os.symlink, dir_path, link_path)
def test_symlink_with_path_ending_with_sep_in_posix(self):
self.check_posix_only()
- dir_path = self.make_path('dir')
+ dir_path = self.make_path("dir")
self.create_dir(dir_path)
- self.assert_raises_os_error(errno.EEXIST, self.os.symlink,
- self.base_path, dir_path + self.os.sep)
+ self.assert_raises_os_error(
+ errno.EEXIST,
+ self.os.symlink,
+ self.base_path,
+ dir_path + self.os.sep,
+ )
- dir_path = self.make_path('bar')
- self.assert_raises_os_error(errno.ENOENT, self.os.symlink,
- self.base_path, dir_path + self.os.sep)
+ dir_path = self.make_path("bar")
+ self.assert_raises_os_error(
+ errno.ENOENT,
+ self.os.symlink,
+ self.base_path,
+ dir_path + self.os.sep,
+ )
def test_symlink_with_path_ending_with_sep_in_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- dir_path = self.make_path('dir')
+ dir_path = self.make_path("dir")
self.create_dir(dir_path)
- self.assert_raises_os_error(errno.EEXIST, self.os.symlink,
- self.base_path, dir_path + self.os.sep)
+ self.assert_raises_os_error(
+ errno.EEXIST,
+ self.os.symlink,
+ self.base_path,
+ dir_path + self.os.sep,
+ )
- dir_path = self.make_path('bar')
+ dir_path = self.make_path("bar")
# does not raise under Windows
self.os.symlink(self.base_path, dir_path + self.os.sep)
def test_broken_symlink_with_trailing_sep_posix(self):
# Regression test for #390
self.check_linux_only()
- path0 = self.make_path('foo') + self.os.sep
- self.assert_raises_os_error(
- errno.ENOENT, self.os.symlink, path0, path0)
+ path0 = self.make_path("foo") + self.os.sep
+ self.assert_raises_os_error(errno.ENOENT, self.os.symlink, path0, path0)
def test_broken_symlink_with_trailing_sep_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- path0 = self.make_path('foo') + self.os.sep
- self.assert_raises_os_error(
- errno.EINVAL, self.os.symlink, path0, path0)
+ path0 = self.make_path("foo") + self.os.sep
+ self.assert_raises_os_error(errno.EINVAL, self.os.symlink, path0, path0)
def test_rename_symlink_with_trailing_sep_linux(self):
# Regression test for #391
self.check_linux_only()
- path = self.make_path('foo')
+ path = self.make_path("foo")
self.os.symlink(self.base_path, path)
- self.assert_raises_os_error(errno.ENOTDIR, self.os.rename,
- path + self.os.sep, self.base_path)
+ self.assert_raises_os_error(
+ errno.ENOTDIR, self.os.rename, path + self.os.sep, self.base_path
+ )
def test_rename_symlink_with_trailing_sep_macos(self):
# Regression test for #391
self.check_macos_only()
- path = self.make_path('foo')
+ path = self.make_path("foo")
self.os.symlink(self.base_path, path)
self.os.rename(path + self.os.sep, self.base_path)
def test_rename_symlink_with_trailing_sep_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- path = self.make_path('foo')
+ path = self.make_path("foo")
self.os.symlink(self.base_path, path)
- self.assert_raises_os_error(errno.EEXIST, self.os.rename,
- path + self.os.sep, self.base_path)
+ self.assert_raises_os_error(
+ errno.EEXIST, self.os.rename, path + self.os.sep, self.base_path
+ )
def test_rename_symlink_to_other_case(self):
# Regression test for #389
self.skip_if_symlink_not_supported()
- link_path = self.make_path('foo')
+ link_path = self.make_path("foo")
self.os.symlink(self.base_path, link_path)
- link_to_link_path = self.make_path('BAR')
+ link_to_link_path = self.make_path("BAR")
self.os.symlink(link_path, link_to_link_path)
- new_link_to_link_path = self.os.path.join(link_path, 'bar')
+ new_link_to_link_path = self.os.path.join(link_path, "bar")
self.os.rename(link_to_link_path, new_link_to_link_path)
- self.assertEqual(['bar', 'foo'],
- sorted(self.os.listdir(new_link_to_link_path)))
+ self.assertEqual(["bar", "foo"], sorted(self.os.listdir(new_link_to_link_path)))
def create_broken_link_path_with_trailing_sep(self):
# Regression tests for #396
self.skip_if_symlink_not_supported()
- link_path = self.make_path('link')
- target_path = self.make_path('target')
+ link_path = self.make_path("link")
+ target_path = self.make_path("target")
self.os.symlink(target_path, link_path)
link_path += self.os.sep
return link_path
@@ -2353,19 +2400,22 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.check_linux_only()
link_path = self.create_broken_link_path_with_trailing_sep()
self.assert_raises_os_error(
- errno.ENOTDIR, self.os.rename, link_path, self.make_path('target'))
+ errno.ENOTDIR, self.os.rename, link_path, self.make_path("target")
+ )
def test_rename_broken_link_with_trailing_sep_macos(self):
self.check_macos_only()
link_path = self.create_broken_link_path_with_trailing_sep()
self.assert_raises_os_error(
- errno.ENOENT, self.os.rename, link_path, self.make_path('target'))
+ errno.ENOENT, self.os.rename, link_path, self.make_path("target")
+ )
def test_rename_broken_link_with_trailing_sep_windows(self):
self.check_windows_only()
link_path = self.create_broken_link_path_with_trailing_sep()
self.assert_raises_os_error(
- errno.EINVAL, self.os.rename, link_path, self.make_path('target'))
+ errno.EINVAL, self.os.rename, link_path, self.make_path("target")
+ )
def test_readlink_broken_link_with_trailing_sep_posix(self):
self.check_posix_only()
@@ -2388,26 +2438,27 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_rename_link_with_trailing_sep_to_self_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- path = self.make_path('foo')
+ path = self.make_path("foo")
self.os.symlink(self.base_path, path)
self.os.rename(path + self.os.sep, path) # no error
def test_rename_link_with_trailing_sep_to_self_posix(self):
# Regression test for #395
self.check_posix_only()
- path = self.make_path('foo')
+ path = self.make_path("foo")
self.os.symlink(self.base_path, path)
self.assert_raises_os_error(
- errno.ENOTDIR, self.os.rename, path + self.os.sep, path)
+ errno.ENOTDIR, self.os.rename, path + self.os.sep, path
+ )
def check_open_broken_symlink_to_path_with_trailing_sep(self, error):
# Regression tests for #397
self.skip_if_symlink_not_supported()
- target_path = self.make_path('target') + self.os.sep
- link_path = self.make_path('link')
+ target_path = self.make_path("target") + self.os.sep
+ link_path = self.make_path("link")
self.os.symlink(target_path, link_path)
- self.assert_raises_os_error(error, self.open, link_path, 'a')
- self.assert_raises_os_error(error, self.open, link_path, 'w')
+ self.assert_raises_os_error(error, self.open, link_path, "a")
+ self.assert_raises_os_error(error, self.open, link_path, "w")
def test_open_broken_symlink_to_path_with_trailing_sep_linux(self):
self.check_linux_only()
@@ -2424,11 +2475,12 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def check_link_path_ending_with_sep(self, error):
# Regression tests for #399
self.skip_if_symlink_not_supported()
- file_path = self.make_path('foo')
- link_path = self.make_path('link')
- with self.open(file_path, 'w'):
+ file_path = self.make_path("foo")
+ link_path = self.make_path("link")
+ with self.open(file_path, "w"):
self.assert_raises_os_error(
- error, self.os.link, file_path + self.os.sep, link_path)
+ error, self.os.link, file_path + self.os.sep, link_path
+ )
def test_link_path_ending_with_sep_posix(self):
self.check_posix_only()
@@ -2441,27 +2493,27 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_link_to_path_ending_with_sep_posix(self):
# regression test for #407
self.check_posix_only()
- path0 = self.make_path('foo') + self.os.sep
- path1 = self.make_path('bar')
- with self.open(path1, 'w'):
- self.assert_raises_os_error(errno.ENOENT,
- self.os.link, path1, path0)
+ path0 = self.make_path("foo") + self.os.sep
+ path1 = self.make_path("bar")
+ with self.open(path1, "w"):
+ self.assert_raises_os_error(errno.ENOENT, self.os.link, path1, path0)
def test_link_to_path_ending_with_sep_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- path0 = self.make_path('foo') + self.os.sep
- path1 = self.make_path('bar')
- with self.open(path1, 'w'):
+ path0 = self.make_path("foo") + self.os.sep
+ path1 = self.make_path("bar")
+ with self.open(path1, "w"):
self.os.link(path1, path0)
self.assertTrue(self.os.path.exists(path1))
def check_rename_to_path_ending_with_sep(self, error):
# Regression tests for #400
- file_path = self.make_path('foo')
- with self.open(file_path, 'w'):
+ file_path = self.make_path("foo")
+ with self.open(file_path, "w"):
self.assert_raises_os_error(
- error, self.os.rename, file_path + self.os.sep, file_path)
+ error, self.os.rename, file_path + self.os.sep, file_path
+ )
def test_rename_to_path_ending_with_sep_posix(self):
self.check_posix_only()
@@ -2473,19 +2525,20 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_rmdir_link_with_trailing_sep_linux(self):
self.check_linux_only()
- dir_path = self.make_path('foo')
+ dir_path = self.make_path("foo")
self.os.mkdir(dir_path)
- link_path = self.make_path('link')
+ link_path = self.make_path("link")
self.os.symlink(dir_path, link_path)
self.assert_raises_os_error(
- errno.ENOTDIR, self.os.rmdir, link_path + self.os.sep)
+ errno.ENOTDIR, self.os.rmdir, link_path + self.os.sep
+ )
def test_rmdir_link_with_trailing_sep_macos(self):
# Regression test for #398
self.check_macos_only()
- dir_path = self.make_path('foo')
+ dir_path = self.make_path("foo")
self.os.mkdir(dir_path)
- link_path = self.make_path('link')
+ link_path = self.make_path("link")
self.os.symlink(dir_path, link_path)
self.os.rmdir(link_path + self.os.sep)
self.assertFalse(self.os.path.exists(link_path))
@@ -2493,27 +2546,26 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_rmdir_link_with_trailing_sep_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- dir_path = self.make_path('foo')
+ dir_path = self.make_path("foo")
self.os.mkdir(dir_path)
- link_path = self.make_path('link')
+ link_path = self.make_path("link")
self.os.symlink(dir_path, link_path)
self.os.rmdir(link_path + self.os.sep)
self.assertFalse(self.os.path.exists(link_path))
def test_readlink_circular_link_with_trailing_sep_linux(self):
self.check_linux_only()
- path1 = self.make_path('foo')
- path0 = self.make_path('bar')
+ path1 = self.make_path("foo")
+ path0 = self.make_path("bar")
self.os.symlink(path0, path1)
self.os.symlink(path1, path0)
- self.assert_raises_os_error(
- errno.ELOOP, self.os.readlink, path0 + self.os.sep)
+ self.assert_raises_os_error(errno.ELOOP, self.os.readlink, path0 + self.os.sep)
def test_readlink_circular_link_with_trailing_sep_macos(self):
# Regression test for #392
self.check_macos_only()
- path1 = self.make_path('foo')
- path0 = self.make_path('bar')
+ path1 = self.make_path("foo")
+ path0 = self.make_path("bar")
self.os.symlink(path0, path1)
self.os.symlink(path1, path0)
self.assertEqual(path0, self.os.readlink(path0 + self.os.sep))
@@ -2521,27 +2573,26 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_readlink_circular_link_with_trailing_sep_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- path1 = self.make_path('foo')
- path0 = self.make_path('bar')
+ path1 = self.make_path("foo")
+ path0 = self.make_path("bar")
self.os.symlink(path0, path1)
self.os.symlink(path1, path0)
- self.assert_raises_os_error(
- errno.EINVAL, self.os.readlink, path0 + self.os.sep)
+ self.assert_raises_os_error(errno.EINVAL, self.os.readlink, path0 + self.os.sep)
# hard link related tests
def test_link_bogus(self):
# trying to create a link from a non-existent file should fail
self.skip_if_symlink_not_supported()
- self.assert_raises_os_error(errno.ENOENT,
- self.os.link, '/nonexistent_source',
- '/link_dest')
+ self.assert_raises_os_error(
+ errno.ENOENT, self.os.link, "/nonexistent_source", "/link_dest"
+ )
def test_link_delete(self):
self.skip_if_symlink_not_supported()
- file1_path = self.make_path('test_file1')
- file2_path = self.make_path('test_file2')
- contents1 = 'abcdef'
+ file1_path = self.make_path("test_file1")
+ file2_path = self.make_path("test_file2")
+ contents1 = "abcdef"
# Create file
self.create_file(file1_path, contents=contents1)
# link to second file
@@ -2556,10 +2607,10 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_link_update(self):
self.skip_if_symlink_not_supported()
- file1_path = self.make_path('test_file1')
- file2_path = self.make_path('test_file2')
- contents1 = 'abcdef'
- contents2 = 'ghijkl'
+ file1_path = self.make_path("test_file1")
+ file2_path = self.make_path("test_file2")
+ contents1 = "abcdef"
+ contents2 = "ghijkl"
# Create file and link
self.create_file(file1_path, contents=contents1)
self.os.link(file1_path, file2_path)
@@ -2567,7 +2618,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
with self.open(file2_path) as f:
self.assertEqual(f.read(), contents1)
# update the first file
- with self.open(file1_path, 'w') as f:
+ with self.open(file1_path, "w") as f:
f.write(contents2)
# assert that second file contains contents2
with self.open(file2_path) as f:
@@ -2575,46 +2626,44 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_link_non_existent_parent(self):
self.skip_if_symlink_not_supported()
- file1_path = self.make_path('test_file1')
- breaking_link_path = self.make_path('nonexistent', 'test_file2')
- contents1 = 'abcdef'
+ file1_path = self.make_path("test_file1")
+ breaking_link_path = self.make_path("nonexistent", "test_file2")
+ contents1 = "abcdef"
# Create file and link
self.create_file(file1_path, contents=contents1)
# trying to create a link under a non-existent directory should fail
self.assert_raises_os_error(
- errno.ENOENT, self.os.link, file1_path, breaking_link_path)
+ errno.ENOENT, self.os.link, file1_path, breaking_link_path
+ )
def test_link_is_existing_file(self):
self.skip_if_symlink_not_supported()
- file_path = self.make_path('foo', 'bar')
+ file_path = self.make_path("foo", "bar")
self.create_file(file_path)
- self.assert_raises_os_error(errno.EEXIST, self.os.link, file_path,
- file_path)
+ self.assert_raises_os_error(errno.EEXIST, self.os.link, file_path, file_path)
def test_link_target_is_dir_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- dir_path = self.make_path('foo', 'bar')
- link_path = self.os.path.join(dir_path, 'link')
+ dir_path = self.make_path("foo", "bar")
+ link_path = self.os.path.join(dir_path, "link")
self.create_dir(dir_path)
- self.assert_raises_os_error(errno.EACCES, self.os.link, dir_path,
- link_path)
+ self.assert_raises_os_error(errno.EACCES, self.os.link, dir_path, link_path)
def test_link_target_is_dir_posix(self):
self.check_posix_only()
- dir_path = self.make_path('foo', 'bar')
- link_path = self.os.path.join(dir_path, 'link')
+ dir_path = self.make_path("foo", "bar")
+ link_path = self.os.path.join(dir_path, "link")
self.create_dir(dir_path)
- self.assert_raises_os_error(errno.EPERM, self.os.link, dir_path,
- link_path)
+ self.assert_raises_os_error(errno.EPERM, self.os.link, dir_path, link_path)
def test_link_count1(self):
"""Test that hard link counts are updated correctly."""
self.skip_if_symlink_not_supported()
- file1_path = self.make_path('test_file1')
- file2_path = self.make_path('test_file2')
- file3_path = self.make_path('test_file3')
+ file1_path = self.make_path("test_file1")
+ file2_path = self.make_path("test_file2")
+ file3_path = self.make_path("test_file3")
self.create_file(file1_path)
# initial link count should be one
self.assertEqual(self.os.stat(file1_path).st_nlink, 1)
@@ -2637,15 +2686,15 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_nlink_for_directories(self):
self.skip_real_fs()
- self.create_dir(self.make_path('foo', 'bar'))
- self.create_file(self.make_path('foo', 'baz'))
- self.assertEqual(2, self.filesystem.get_object(
- self.make_path('foo', 'bar')).st_nlink)
- self.assertEqual(4, self.filesystem.get_object(
- self.make_path('foo')).st_nlink)
- self.create_file(self.make_path('foo', 'baz2'))
- self.assertEqual(5, self.filesystem.get_object(
- self.make_path('foo')).st_nlink)
+ self.create_dir(self.make_path("foo", "bar"))
+ self.create_file(self.make_path("foo", "baz"))
+ self.assertEqual(
+ 2,
+ self.filesystem.get_object(self.make_path("foo", "bar")).st_nlink,
+ )
+ self.assertEqual(4, self.filesystem.get_object(self.make_path("foo")).st_nlink)
+ self.create_file(self.make_path("foo", "baz2"))
+ self.assertEqual(5, self.filesystem.get_object(self.make_path("foo")).st_nlink)
def test_umask(self):
self.check_posix_only()
@@ -2657,11 +2706,11 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
"""mkdir creates a directory with umask applied."""
self.check_posix_only()
self.os.umask(0o22)
- dir1 = self.make_path('dir1')
+ dir1 = self.make_path("dir1")
self.os.mkdir(dir1)
self.assert_mode_equal(0o755, self.os.stat(dir1).st_mode)
self.os.umask(0o67)
- dir2 = self.make_path('dir2')
+ dir2 = self.make_path("dir2")
self.os.mkdir(dir2)
self.assert_mode_equal(0o710, self.os.stat(dir2).st_mode)
@@ -2669,28 +2718,28 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
"""makedirs creates a directories with umask applied."""
self.check_posix_only()
self.os.umask(0o22)
- self.os.makedirs(self.make_path('p1', 'dir1'))
+ self.os.makedirs(self.make_path("p1", "dir1"))
+ self.assert_mode_equal(0o755, self.os.stat(self.make_path("p1")).st_mode)
self.assert_mode_equal(
- 0o755, self.os.stat(self.make_path('p1')).st_mode)
- self.assert_mode_equal(
- 0o755, self.os.stat(self.make_path('p1', 'dir1')).st_mode)
+ 0o755, self.os.stat(self.make_path("p1", "dir1")).st_mode
+ )
self.os.umask(0o67)
- self.os.makedirs(self.make_path('p2', 'dir2'))
- self.assert_mode_equal(
- 0o710, self.os.stat(self.make_path('p2')).st_mode)
+ self.os.makedirs(self.make_path("p2", "dir2"))
+ self.assert_mode_equal(0o710, self.os.stat(self.make_path("p2")).st_mode)
self.assert_mode_equal(
- 0o710, self.os.stat(self.make_path('p2', 'dir2')).st_mode)
+ 0o710, self.os.stat(self.make_path("p2", "dir2")).st_mode
+ )
def test_mknod_umask_applied(self):
"""mkdir creates a device with umask applied."""
# skipping MacOs due to mknod permission issues
self.check_linux_only()
self.os.umask(0o22)
- node1 = self.make_path('nod1')
+ node1 = self.make_path("nod1")
self.os.mknod(node1, stat.S_IFREG | 0o666)
self.assert_mode_equal(0o644, self.os.stat(node1).st_mode)
self.os.umask(0o27)
- node2 = self.make_path('nod2')
+ node2 = self.make_path("nod2")
self.os.mknod(node2, stat.S_IFREG | 0o666)
self.assert_mode_equal(0o640, self.os.stat(node2).st_mode)
@@ -2698,12 +2747,12 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
"""open creates a file with umask applied."""
self.check_posix_only()
self.os.umask(0o22)
- file1 = self.make_path('file1')
- self.open(file1, 'w').close()
+ file1 = self.make_path("file1")
+ self.open(file1, "w").close()
self.assert_mode_equal(0o644, self.os.stat(file1).st_mode)
self.os.umask(0o27)
- file2 = self.make_path('file2')
- self.open(file2, 'w').close()
+ file2 = self.make_path("file2")
+ self.open(file2, "w").close()
self.assert_mode_equal(0o640, self.os.stat(file2).st_mode)
def test_open_pipe(self):
@@ -2712,7 +2761,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
self.os.close(write_fd)
def test_open_pipe_with_existing_fd(self):
- file1 = self.make_path('file1')
+ file1 = self.make_path("file1")
fd = self.os.open(file1, os.O_CREAT)
read_fd, write_fd = self.os.pipe()
self.assertGreater(read_fd, fd)
@@ -2722,7 +2771,7 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_open_file_with_existing_pipe(self):
read_fd, write_fd = self.os.pipe()
- file1 = self.make_path('file1')
+ file1 = self.make_path("file1")
fd = self.os.open(file1, os.O_CREAT)
self.assertGreater(fd, write_fd)
self.os.close(read_fd)
@@ -2731,8 +2780,8 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
def test_read_write_pipe(self):
read_fd, write_fd = self.os.pipe()
- self.assertEqual(4, self.os.write(write_fd, b'test'))
- self.assertEqual(b'test', self.os.read(read_fd, 4))
+ self.assertEqual(4, self.os.write(write_fd, b"test"))
+ self.assertEqual(b"test", self.os.read(read_fd, 4))
self.os.close(read_fd)
self.os.close(write_fd)
@@ -2741,78 +2790,96 @@ class FakeOsModuleTest(FakeOsModuleTestBase):
# are out of sync (see #581)
fds = []
for i in range(5):
- path = self.make_path('file' + str(i))
+ path = self.make_path("file" + str(i))
fds.append(self.os.open(path, os.O_CREAT))
- file_path = self.make_path('file.txt')
+ file_path = self.make_path("file.txt")
self.create_file(file_path)
with self.open(file_path):
read_fd, write_fd = self.os.pipe()
- with self.open(write_fd, 'wb') as f:
- self.assertEqual(4, f.write(b'test'))
- with self.open(read_fd, 'rb') as f:
- self.assertEqual(b'test', f.read())
+ with self.open(write_fd, "wb") as f:
+ self.assertEqual(4, f.write(b"test"))
+ with self.open(read_fd, "rb") as f:
+ self.assertEqual(b"test", f.read())
for fd in fds:
self.os.close(fd)
def test_write_to_pipe(self):
read_fd, write_fd = self.os.pipe()
- self.os.write(write_fd, b'test')
- self.assertEqual(b'test', self.os.read(read_fd, 4))
+ self.os.write(write_fd, b"test")
+ self.assertEqual(b"test", self.os.read(read_fd, 4))
self.os.close(read_fd)
self.os.close(write_fd)
+ @unittest.skipIf(
+ sys.platform not in ("win32", "darwin", "linux"),
+ "Pipe implementation may differ on other platforms",
+ )
def test_write_to_read_fd(self):
read_fd, write_fd = self.os.pipe()
- self.assert_raises_os_error(errno.EBADF,
- self.os.write, read_fd, b'test')
+ self.assert_raises_os_error(errno.EBADF, self.os.write, read_fd, b"test")
self.os.close(read_fd)
self.os.close(write_fd)
def test_truncate(self):
- file_path = self.make_path('foo', 'bar')
- self.create_file(file_path, contents='012345678901234567')
+ file_path = self.make_path("foo", "bar")
+ self.create_file(file_path, contents="012345678901234567")
self.os.truncate(file_path, 10)
with self.open(file_path) as f:
- self.assertEqual('0123456789', f.read())
+ self.assertEqual("0123456789", f.read())
def test_truncate_non_existing(self):
- self.assert_raises_os_error(errno.ENOENT, self.os.truncate, 'foo', 10)
+ self.assert_raises_os_error(errno.ENOENT, self.os.truncate, "foo", 10)
def test_truncate_to_larger(self):
- file_path = self.make_path('foo', 'bar')
- self.create_file(file_path, contents='0123456789')
+ file_path = self.make_path("foo", "bar")
+ self.create_file(file_path, contents="0123456789")
fd = self.os.open(file_path, os.O_RDWR)
self.os.truncate(fd, 20)
self.assertEqual(20, self.os.stat(file_path).st_size)
with self.open(file_path) as f:
- self.assertEqual('0123456789' + '\0' * 10, f.read())
+ self.assertEqual("0123456789" + "\0" * 10, f.read())
def test_truncate_with_fd(self):
if os.truncate not in os.supports_fd:
self.skip_real_fs()
self.assert_raises_os_error(errno.EBADF, self.os.ftruncate, 50, 10)
- file_path = self.make_path('some_file')
- self.create_file(file_path, contents='01234567890123456789')
+ file_path = self.make_path("some_file")
+ self.create_file(file_path, contents="01234567890123456789")
fd = self.os.open(file_path, os.O_RDWR)
self.os.truncate(fd, 10)
self.assertEqual(10, self.os.stat(file_path).st_size)
with self.open(file_path) as f:
- self.assertEqual('0123456789', f.read())
+ self.assertEqual("0123456789", f.read())
def test_ftruncate(self):
if self.is_pypy:
# not correctly supported
self.skip_real_fs()
self.assert_raises_os_error(errno.EBADF, self.os.ftruncate, 50, 10)
- file_path = self.make_path('some_file')
- self.create_file(file_path, contents='0123456789012345')
+ file_path = self.make_path("some_file")
+ self.create_file(file_path, contents="0123456789012345")
fd = self.os.open(file_path, os.O_RDWR)
self.os.truncate(fd, 10)
self.assertEqual(10, self.os.stat(file_path).st_size)
with self.open(file_path) as f:
- self.assertEqual('0123456789', f.read())
+ self.assertEqual("0123456789", f.read())
+
+ def test_capabilities(self):
+ """Make sure that the fake capabilities are the same as the real ones."""
+ self.assertEqual(
+ self.os.stat in self.os.supports_follow_symlinks,
+ os.stat in os.supports_follow_symlinks,
+ )
+ self.assertEqual(self.os.stat in self.os.supports_fd, os.stat in os.supports_fd)
+ self.assertEqual(
+ self.os.stat in self.os.supports_dir_fd, os.stat in os.supports_dir_fd
+ )
+ self.assertEqual(
+ self.os.stat in self.os.supports_effective_ids,
+ os.stat in os.supports_effective_ids,
+ )
class RealOsModuleTest(FakeOsModuleTest):
@@ -2829,55 +2896,54 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_chdir_fails_non_directory(self):
"""chdir should raise OSError if the target is not a directory."""
- filename = self.make_path('foo', 'bar')
+ filename = self.make_path("foo", "bar")
self.create_file(filename)
- filename1 = self.make_path('Foo', 'Bar')
+ filename1 = self.make_path("Foo", "Bar")
self.assert_raises_os_error(errno.ENOTDIR, self.os.chdir, filename1)
def test_listdir_returns_list(self):
- directory_root = self.make_path('xyzzy')
+ directory_root = self.make_path("xyzzy")
self.os.mkdir(directory_root)
- directory = self.os.path.join(directory_root, 'bug')
+ directory = self.os.path.join(directory_root, "bug")
self.os.mkdir(directory)
- directory_upper = self.make_path('XYZZY', 'BUG')
- self.create_file(self.make_path(directory, 'foo'))
- self.assertEqual(['foo'], self.os.listdir(directory_upper))
+ directory_upper = self.make_path("XYZZY", "BUG")
+ self.create_file(self.make_path(directory, "foo"))
+ self.assertEqual(["foo"], self.os.listdir(directory_upper))
def test_listdir_on_symlink(self):
self.skip_if_symlink_not_supported()
- directory = self.make_path('xyzzy')
- files = ['foo', 'bar', 'baz']
+ directory = self.make_path("xyzzy")
+ files = ["foo", "bar", "baz"]
for f in files:
self.create_file(self.make_path(directory, f))
- self.create_symlink(self.make_path('symlink'), self.make_path('xyzzy'))
+ self.create_symlink(self.make_path("symlink"), self.make_path("xyzzy"))
files.sort()
- self.assertEqual(files,
- sorted(self.os.listdir(self.make_path('SymLink'))))
+ self.assertEqual(files, sorted(self.os.listdir(self.make_path("SymLink"))))
def test_fdopen_mode(self):
self.skip_real_fs()
- file_path1 = self.make_path('some_file1')
- file_path2 = self.make_path('Some_File1')
- file_path3 = self.make_path('SOME_file1')
- self.create_file(file_path1, contents='contents here1')
+ file_path1 = self.make_path("some_file1")
+ file_path2 = self.make_path("Some_File1")
+ file_path3 = self.make_path("SOME_file1")
+ self.create_file(file_path1, contents="contents here1")
self.os.chmod(file_path2, (stat.S_IFREG | 0o666) ^ stat.S_IWRITE)
- fake_file1 = self.open(file_path3, 'r')
+ fake_file1 = self.open(file_path3, "r")
fileno1 = fake_file1.fileno()
self.os.fdopen(fileno1)
- self.os.fdopen(fileno1, 'r')
+ self.os.fdopen(fileno1, "r")
if not is_root():
- self.assertRaises(OSError, self.os.fdopen, fileno1, 'w')
+ self.assertRaises(OSError, self.os.fdopen, fileno1, "w")
else:
- self.os.fdopen(fileno1, 'w')
+ self.os.fdopen(fileno1, "w")
def test_stat(self):
- directory = self.make_path('xyzzy')
- directory1 = self.make_path('XYZZY')
- file_path = self.os.path.join(directory, 'plugh')
- self.create_file(file_path, contents='ABCDE')
+ directory = self.make_path("xyzzy")
+ directory1 = self.make_path("XYZZY")
+ file_path = self.os.path.join(directory, "plugh")
+ self.create_file(file_path, contents="ABCDE")
self.assertTrue(stat.S_IFDIR & self.os.stat(directory1)[stat.ST_MODE])
- file_path1 = self.os.path.join(directory1, 'Plugh')
+ file_path1 = self.os.path.join(directory1, "Plugh")
self.assertTrue(stat.S_IFREG & self.os.stat(file_path1)[stat.ST_MODE])
self.assertTrue(stat.S_IFREG & self.os.stat(file_path1).st_mode)
self.assertEqual(5, self.os.stat(file_path1)[stat.ST_SIZE])
@@ -2885,48 +2951,51 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_stat_no_follow_symlinks_posix(self):
"""Test that stat with follow_symlinks=False behaves like lstat."""
self.check_posix_only()
- directory = self.make_path('xyzzy')
- base_name = 'plugh'
- file_contents = 'frobozz'
+ directory = self.make_path("xyzzy")
+ base_name = "plugh"
+ file_contents = "frobozz"
# Just make sure we didn't accidentally make our test data meaningless.
self.assertNotEqual(len(base_name), len(file_contents))
file_path = self.os.path.join(directory, base_name)
- link_path = self.os.path.join(directory, 'link')
+ link_path = self.os.path.join(directory, "link")
self.create_file(file_path, contents=file_contents)
self.create_symlink(link_path, base_name)
- self.assertEqual(len(file_contents), self.os.stat(
- file_path.upper(), follow_symlinks=False)[stat.ST_SIZE])
- self.assertEqual(len(base_name), self.os.stat(
- link_path.upper(), follow_symlinks=False)[stat.ST_SIZE])
+ self.assertEqual(
+ len(file_contents),
+ self.os.stat(file_path.upper(), follow_symlinks=False)[stat.ST_SIZE],
+ )
+ self.assertEqual(
+ len(base_name),
+ self.os.stat(link_path.upper(), follow_symlinks=False)[stat.ST_SIZE],
+ )
def test_lstat_posix(self):
self.check_posix_only()
- directory = self.make_path('xyzzy')
- base_name = 'plugh'
- file_contents = 'frobozz'
+ directory = self.make_path("xyzzy")
+ base_name = "plugh"
+ file_contents = "frobozz"
# Just make sure we didn't accidentally make our test data meaningless.
self.assertNotEqual(len(base_name), len(file_contents))
file_path = self.os.path.join(directory, base_name)
- link_path = self.os.path.join(directory, 'link')
+ link_path = self.os.path.join(directory, "link")
self.create_file(file_path, contents=file_contents)
self.create_symlink(link_path, base_name)
- self.assertEqual(len(file_contents),
- self.os.lstat(file_path.upper())[stat.ST_SIZE])
- self.assertEqual(len(base_name),
- self.os.lstat(link_path.upper())[stat.ST_SIZE])
+ self.assertEqual(
+ len(file_contents), self.os.lstat(file_path.upper())[stat.ST_SIZE]
+ )
+ self.assertEqual(len(base_name), self.os.lstat(link_path.upper())[stat.ST_SIZE])
def test_readlink(self):
self.skip_if_symlink_not_supported()
- link_path = self.make_path('foo', 'bar', 'baz')
- target = self.make_path('tarJAY')
+ link_path = self.make_path("foo", "bar", "baz")
+ target = self.make_path("tarJAY")
self.create_symlink(link_path, target)
self.assert_equal_paths(self.os.readlink(link_path.upper()), target)
def check_readlink_raises_if_path_not_a_link(self):
- file_path = self.make_path('foo', 'bar', 'eleventyone')
+ file_path = self.make_path("foo", "bar", "eleventyone")
self.create_file(file_path)
- self.assert_raises_os_error(errno.EINVAL,
- self.os.readlink, file_path.upper())
+ self.assert_raises_os_error(errno.EINVAL, self.os.readlink, file_path.upper())
def test_readlink_raises_if_path_not_a_link_windows(self):
self.check_windows_only()
@@ -2938,13 +3007,11 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
self.check_readlink_raises_if_path_not_a_link()
def check_readlink_raises_if_path_has_file(self, error_subtype):
- self.create_file(self.make_path('a_file'))
- file_path = self.make_path('a_file', 'foo')
- self.assert_raises_os_error(error_subtype,
- self.os.readlink, file_path.upper())
- file_path = self.make_path('a_file', 'foo', 'bar')
- self.assert_raises_os_error(error_subtype,
- self.os.readlink, file_path.upper())
+ self.create_file(self.make_path("a_file"))
+ file_path = self.make_path("a_file", "foo")
+ self.assert_raises_os_error(error_subtype, self.os.readlink, file_path.upper())
+ file_path = self.make_path("a_file", "foo", "bar")
+ self.assert_raises_os_error(error_subtype, self.os.readlink, file_path.upper())
def test_readlink_raises_if_path_has_file_windows(self):
self.check_windows_only()
@@ -2957,31 +3024,35 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_readlink_with_links_in_path(self):
self.skip_if_symlink_not_supported()
- self.create_symlink(self.make_path('meyer', 'lemon', 'pie'),
- self.make_path('yum'))
- self.create_symlink(self.make_path('geo', 'metro'),
- self.make_path('Meyer'))
- self.assert_equal_paths(self.make_path('yum'),
- self.os.readlink(
- self.make_path('Geo', 'Metro',
- 'Lemon', 'Pie')))
+ self.create_symlink(
+ self.make_path("meyer", "lemon", "pie"), self.make_path("yum")
+ )
+ self.create_symlink(self.make_path("geo", "metro"), self.make_path("Meyer"))
+ self.assert_equal_paths(
+ self.make_path("yum"),
+ self.os.readlink(self.make_path("Geo", "Metro", "Lemon", "Pie")),
+ )
def test_readlink_with_chained_links_in_path(self):
self.skip_if_symlink_not_supported()
- self.create_symlink(self.make_path(
- 'eastern', 'european', 'wolfhounds', 'chase'),
- self.make_path('cats'))
- self.create_symlink(self.make_path('russian'),
- self.make_path('Eastern', 'European'))
- self.create_symlink(self.make_path('dogs'),
- self.make_path('Russian', 'Wolfhounds'))
- self.assert_equal_paths(self.make_path('cats'),
- self.os.readlink(
- self.make_path('DOGS', 'Chase')))
+ self.create_symlink(
+ self.make_path("eastern", "european", "wolfhounds", "chase"),
+ self.make_path("cats"),
+ )
+ self.create_symlink(
+ self.make_path("russian"), self.make_path("Eastern", "European")
+ )
+ self.create_symlink(
+ self.make_path("dogs"), self.make_path("Russian", "Wolfhounds")
+ )
+ self.assert_equal_paths(
+ self.make_path("cats"),
+ self.os.readlink(self.make_path("DOGS", "Chase")),
+ )
def check_remove_dir(self, dir_error):
- directory = self.make_path('xyzzy')
- dir_path = self.os.path.join(directory, 'plugh')
+ directory = self.make_path("xyzzy")
+ dir_path = self.os.path.join(directory, "plugh")
self.create_dir(dir_path)
dir_path = dir_path.upper()
self.assertTrue(self.os.path.exists(dir_path.upper()))
@@ -2990,7 +3061,7 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
self.os.chdir(directory)
self.assert_raises_os_error(dir_error, self.os.remove, dir_path)
self.assertTrue(self.os.path.exists(dir_path))
- self.assert_raises_os_error(errno.ENOENT, self.os.remove, '/Plugh')
+ self.assert_raises_os_error(errno.ENOENT, self.os.remove, "/Plugh")
def test_remove_dir_mac_os(self):
self.check_macos_only()
@@ -3001,16 +3072,16 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
self.check_remove_dir(errno.EACCES)
def test_remove_file(self):
- directory = self.make_path('zzy')
- file_path = self.os.path.join(directory, 'plugh')
+ directory = self.make_path("zzy")
+ file_path = self.os.path.join(directory, "plugh")
self.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path.upper()))
self.os.remove(file_path.upper())
self.assertFalse(self.os.path.exists(file_path))
def test_remove_file_no_directory(self):
- directory = self.make_path('zzy')
- file_name = 'plugh'
+ directory = self.make_path("zzy")
+ file_name = "plugh"
file_path = self.os.path.join(directory, file_name)
self.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path))
@@ -3020,29 +3091,28 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_remove_open_file_fails_under_windows(self):
self.check_windows_only()
- path = self.make_path('foo', 'bar')
+ path = self.make_path("foo", "bar")
self.create_file(path)
- with self.open(path, 'r'):
- self.assert_raises_os_error(errno.EACCES,
- self.os.remove, path.upper())
+ with self.open(path, "r"):
+ self.assert_raises_os_error(errno.EACCES, self.os.remove, path.upper())
self.assertTrue(self.os.path.exists(path))
def test_remove_open_file_possible_under_posix(self):
self.check_posix_only()
- path = self.make_path('foo', 'bar')
+ path = self.make_path("foo", "bar")
self.create_file(path)
- self.open(path, 'r')
+ self.open(path, "r")
self.os.remove(path.upper())
self.assertFalse(self.os.path.exists(path))
def test_remove_file_relative_path(self):
self.skip_real_fs()
original_dir = self.os.getcwd()
- directory = self.make_path('zzy')
- subdirectory = self.os.path.join(directory, 'zzy')
- file_name = 'plugh'
+ directory = self.make_path("zzy")
+ subdirectory = self.os.path.join(directory, "zzy")
+ file_name = "plugh"
file_path = self.os.path.join(directory, file_name)
- file_path_relative = self.os.path.join('..', file_name)
+ file_path_relative = self.os.path.join("..", file_name)
self.create_file(file_path.upper())
self.assertTrue(self.os.path.exists(file_path))
self.create_dir(subdirectory)
@@ -3054,10 +3124,9 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
self.assertFalse(self.os.path.exists(file_path))
def check_remove_dir_raises_error(self, dir_error):
- directory = self.make_path('zzy')
+ directory = self.make_path("zzy")
self.create_dir(directory)
- self.assert_raises_os_error(dir_error,
- self.os.remove, directory.upper())
+ self.assert_raises_os_error(dir_error, self.os.remove, directory.upper())
def test_remove_dir_raises_error_mac_os(self):
self.check_macos_only()
@@ -3069,8 +3138,8 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_remove_symlink_to_dir(self):
self.skip_if_symlink_not_supported()
- directory = self.make_path('zzy')
- link = self.make_path('link_to_dir')
+ directory = self.make_path("zzy")
+ link = self.make_path("link_to_dir")
self.create_dir(directory)
self.os.symlink(directory, link)
self.assertTrue(self.os.path.exists(directory))
@@ -3081,42 +3150,40 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_rename_dir_to_symlink_posix(self):
self.check_posix_only()
- link_path = self.make_path('link')
- dir_path = self.make_path('dir')
- link_target = self.os.path.join(dir_path, 'link_target')
+ link_path = self.make_path("link")
+ dir_path = self.make_path("dir")
+ link_target = self.os.path.join(dir_path, "link_target")
self.create_dir(dir_path)
self.os.symlink(link_target.upper(), link_path.upper())
- self.assert_raises_os_error(errno.ENOTDIR, self.os.rename, dir_path,
- link_path)
+ self.assert_raises_os_error(errno.ENOTDIR, self.os.rename, dir_path, link_path)
def test_rename_dir_to_symlink_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- link_path = self.make_path('link')
- dir_path = self.make_path('dir')
- link_target = self.os.path.join(dir_path, 'link_target')
+ link_path = self.make_path("link")
+ dir_path = self.make_path("dir")
+ link_target = self.os.path.join(dir_path, "link_target")
self.create_dir(dir_path)
self.os.symlink(link_target.upper(), link_path.upper())
- self.assert_raises_os_error(errno.EEXIST, self.os.rename, dir_path,
- link_path)
+ self.assert_raises_os_error(errno.EEXIST, self.os.rename, dir_path, link_path)
def test_rename_dir_to_existing_dir(self):
# Regression test for #317
self.check_posix_only()
- dest_dir_path = self.make_path('Dest')
+ dest_dir_path = self.make_path("Dest")
# seems to behave differently under different MacOS versions
self.skip_real_fs()
- new_dest_dir_path = self.make_path('dest')
+ new_dest_dir_path = self.make_path("dest")
self.os.mkdir(dest_dir_path)
- source_dir_path = self.make_path('src')
+ source_dir_path = self.make_path("src")
self.os.mkdir(source_dir_path)
self.os.rename(source_dir_path, new_dest_dir_path)
- self.assertEqual(['dest'], self.os.listdir(self.base_path))
+ self.assertEqual(["dest"], self.os.listdir(self.base_path))
def test_rename_file_to_symlink(self):
self.check_posix_only()
- link_path = self.make_path('file_link')
- file_path = self.make_path('file')
+ link_path = self.make_path("file_link")
+ file_path = self.make_path("file")
self.os.symlink(file_path, link_path)
self.create_file(file_path)
self.os.rename(file_path.upper(), link_path)
@@ -3126,10 +3193,10 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_rename_symlink_to_symlink(self):
self.check_posix_only()
- base_path = self.make_path('foo', 'bar')
+ base_path = self.make_path("foo", "bar")
self.create_dir(base_path)
- link_path1 = self.os.path.join(base_path, 'link1')
- link_path2 = self.os.path.join(base_path, 'link2')
+ link_path1 = self.os.path.join(base_path, "link1")
+ link_path2 = self.os.path.join(base_path, "link2")
self.os.symlink(base_path.upper(), link_path1)
self.os.symlink(base_path, link_path2)
self.os.rename(link_path1.upper(), link_path2.upper())
@@ -3138,64 +3205,72 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_rename_symlink_to_symlink_for_parent_raises(self):
self.check_posix_only()
- dir_link = self.make_path('dir_link')
- dir_path = self.make_path('dir')
- dir_in_dir_path = self.os.path.join(dir_link, 'inner_dir')
+ dir_link = self.make_path("dir_link")
+ dir_path = self.make_path("dir")
+ dir_in_dir_path = self.os.path.join(dir_link, "inner_dir")
self.create_dir(dir_path)
self.os.symlink(dir_path.upper(), dir_link)
self.create_dir(dir_in_dir_path)
- self.assert_raises_os_error(errno.EINVAL, self.os.rename, dir_path,
- dir_in_dir_path.upper())
+ self.assert_raises_os_error(
+ errno.EINVAL, self.os.rename, dir_path, dir_in_dir_path.upper()
+ )
def test_rename_directory_to_linked_dir(self):
# Regression test for #314
self.skip_if_symlink_not_supported()
- link_path = self.make_path('link')
+ link_path = self.make_path("link")
self.os.symlink(self.base_path, link_path)
- link_subdir = self.os.path.join(link_path, 'dir')
- dir_path = self.make_path('Dir')
+ link_subdir = self.os.path.join(link_path, "dir")
+ dir_path = self.make_path("Dir")
self.os.mkdir(dir_path)
self.os.rename(dir_path, link_subdir)
- self.assertEqual(['dir', 'link'],
- sorted(self.os.listdir(self.base_path)))
+ self.assertEqual(["dir", "link"], sorted(self.os.listdir(self.base_path)))
def test_recursive_rename_raises(self):
self.check_posix_only()
- base_path = self.make_path('foo', 'bar')
+ base_path = self.make_path("foo", "bar")
self.create_dir(base_path)
- new_path = self.os.path.join(base_path, 'new_dir')
- self.assert_raises_os_error(errno.EINVAL, self.os.rename,
- base_path.upper(), new_path)
+ new_path = self.os.path.join(base_path, "new_dir")
+ self.assert_raises_os_error(
+ errno.EINVAL, self.os.rename, base_path.upper(), new_path
+ )
def test_rename_with_target_parent_file_raises_posix(self):
self.check_posix_only()
- file_path = self.make_path('foo', 'baz')
+ file_path = self.make_path("foo", "baz")
self.create_file(file_path)
- self.assert_raises_os_error(errno.ENOTDIR, self.os.rename, file_path,
- file_path.upper() + '/new')
+ self.assert_raises_os_error(
+ errno.ENOTDIR,
+ self.os.rename,
+ file_path,
+ file_path.upper() + "/new",
+ )
def test_rename_with_target_parent_file_raises_windows(self):
self.check_windows_only()
- file_path = self.make_path('foo', 'baz')
+ file_path = self.make_path("foo", "baz")
self.create_file(file_path)
self.assert_raises_os_error(
- errno.EACCES, self.os.rename, file_path,
- self.os.path.join(file_path.upper(), 'new'))
+ errno.EACCES,
+ self.os.rename,
+ file_path,
+ self.os.path.join(file_path.upper(), "new"),
+ )
def test_rename_looping_symlink(self):
# Regression test for #315
self.skip_if_symlink_not_supported()
- path_lower = self.make_path('baz')
- path_upper = self.make_path('BAZ')
+ path_lower = self.make_path("baz")
+ path_upper = self.make_path("BAZ")
self.os.symlink(path_lower, path_upper)
self.os.rename(path_upper, path_lower)
- self.assertEqual(['baz'], self.os.listdir(self.base_path))
+ self.assertEqual(["baz"], self.os.listdir(self.base_path))
def test_rename_symlink_to_source(self):
self.check_posix_only()
- base_path = self.make_path('foo')
- link_path = self.os.path.join(base_path, 'slink')
- file_path = self.os.path.join(base_path, 'file')
+ base_path = self.make_path("foo")
+ link_path = self.os.path.join(base_path, "slink")
+ file_path = self.os.path.join(base_path, "file")
self.create_file(file_path)
self.os.symlink(file_path, link_path)
self.os.rename(link_path.upper(), file_path.upper())
@@ -3203,20 +3278,21 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_rename_symlink_to_dir_raises(self):
self.check_posix_only()
- base_path = self.make_path('foo', 'bar')
- link_path = self.os.path.join(base_path, 'dir_link')
- dir_path = self.os.path.join(base_path, 'dir')
+ base_path = self.make_path("foo", "bar")
+ link_path = self.os.path.join(base_path, "dir_link")
+ dir_path = self.os.path.join(base_path, "dir")
self.create_dir(dir_path)
self.os.symlink(dir_path, link_path.upper())
- self.assert_raises_os_error(errno.EISDIR, self.os.rename, link_path,
- dir_path.upper())
+ self.assert_raises_os_error(
+ errno.EISDIR, self.os.rename, link_path, dir_path.upper()
+ )
def test_rename_broken_symlink(self):
self.check_posix_only()
- base_path = self.make_path('foo')
+ base_path = self.make_path("foo")
self.create_dir(base_path)
- link_path = self.os.path.join(base_path, 'slink')
- file_path = self.os.path.join(base_path, 'file')
+ link_path = self.os.path.join(base_path, "slink")
+ file_path = self.os.path.join(base_path, "file")
self.os.symlink(file_path.upper(), link_path)
self.os.rename(link_path.upper(), file_path)
self.assertFalse(self.os.path.exists(file_path))
@@ -3225,49 +3301,48 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_change_case_in_case_insensitive_file_system(self):
"""Can use `rename()` to change filename case in a case-insensitive
- file system."""
- old_file_path = self.make_path('fileName')
- new_file_path = self.make_path('FileNAME')
- self.create_file(old_file_path, contents='test contents')
- self.assertEqual(['fileName'], self.os.listdir(self.base_path))
+ file system."""
+ old_file_path = self.make_path("fileName")
+ new_file_path = self.make_path("FileNAME")
+ self.create_file(old_file_path, contents="test contents")
+ self.assertEqual(["fileName"], self.os.listdir(self.base_path))
self.os.rename(old_file_path, new_file_path)
self.assertTrue(self.os.path.exists(old_file_path))
self.assertTrue(self.os.path.exists(new_file_path))
- self.assertEqual(['FileNAME'], self.os.listdir(self.base_path))
+ self.assertEqual(["FileNAME"], self.os.listdir(self.base_path))
def test_rename_symlink_with_changed_case(self):
# Regression test for #313
self.skip_if_symlink_not_supported()
- link_path = self.make_path('link')
+ link_path = self.make_path("link")
self.os.symlink(self.base_path, link_path)
- link_path = self.os.path.join(link_path, 'link')
- link_path_upper = self.make_path('link', 'LINK')
+ link_path = self.os.path.join(link_path, "link")
+ link_path_upper = self.make_path("link", "LINK")
self.os.rename(link_path_upper, link_path)
def test_rename_directory(self):
"""Can rename a directory to an unused name."""
- for old_path, new_path in [('wxyyw', 'xyzzy'), ('abccb', 'cdeed')]:
+ for old_path, new_path in [("wxyyw", "xyzzy"), ("abccb", "cdeed")]:
old_path = self.make_path(old_path)
new_path = self.make_path(new_path)
- self.create_file(self.os.path.join(old_path, 'plugh'),
- contents='test')
+ self.create_file(self.os.path.join(old_path, "plugh"), contents="test")
self.assertTrue(self.os.path.exists(old_path))
self.assertFalse(self.os.path.exists(new_path))
self.os.rename(old_path.upper(), new_path.upper())
self.assertFalse(self.os.path.exists(old_path))
self.assertTrue(self.os.path.exists(new_path))
- self.check_contents(self.os.path.join(new_path, 'plugh'), 'test')
+ self.check_contents(self.os.path.join(new_path, "plugh"), "test")
if not self.use_real_fs():
- self.assertEqual(3,
- self.filesystem.get_object(new_path).st_nlink)
+ self.assertEqual(3, self.filesystem.get_object(new_path).st_nlink)
def check_rename_directory_to_existing_file_raises(self, error_nr):
- dir_path = self.make_path('dir')
- file_path = self.make_path('file')
+ dir_path = self.make_path("dir")
+ file_path = self.make_path("file")
self.create_dir(dir_path)
self.create_file(file_path)
- self.assert_raises_os_error(error_nr, self.os.rename, dir_path,
- file_path.upper())
+ self.assert_raises_os_error(
+ error_nr, self.os.rename, dir_path, file_path.upper()
+ )
def test_rename_directory_to_existing_file_raises_posix(self):
self.check_posix_only()
@@ -3280,20 +3355,20 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_rename_to_existing_directory_should_raise_under_windows(self):
"""Renaming to an existing directory raises OSError under Windows."""
self.check_windows_only()
- old_path = self.make_path('foo', 'bar')
- new_path = self.make_path('foo', 'baz')
+ old_path = self.make_path("foo", "bar")
+ new_path = self.make_path("foo", "baz")
self.create_dir(old_path)
self.create_dir(new_path)
- self.assert_raises_os_error(errno.EEXIST, self.os.rename,
- old_path.upper(),
- new_path.upper())
+ self.assert_raises_os_error(
+ errno.EEXIST, self.os.rename, old_path.upper(), new_path.upper()
+ )
def test_rename_to_a_hardlink_of_same_file_should_do_nothing(self):
self.skip_real_fs_failure(skip_posix=False)
self.skip_if_symlink_not_supported()
- file_path = self.make_path('dir', 'file')
+ file_path = self.make_path("dir", "file")
self.create_file(file_path)
- link_path = self.make_path('link')
+ link_path = self.make_path("link")
self.os.link(file_path.upper(), link_path)
self.os.rename(file_path, link_path.upper())
self.assertTrue(self.os.path.exists(file_path))
@@ -3301,9 +3376,9 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_rename_with_incorrect_source_case(self):
# Regression test for #308
- base_path = self.make_path('foo')
- path0 = self.os.path.join(base_path, 'bar')
- path1 = self.os.path.join(base_path, 'Bar')
+ base_path = self.make_path("foo")
+ path0 = self.os.path.join(base_path, "bar")
+ path1 = self.os.path.join(base_path, "Bar")
self.create_dir(path0)
self.os.rename(path1, path0)
self.assertTrue(self.os.path.exists(path0))
@@ -3316,7 +3391,7 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
path0 = self.make_path("beta", "Beta")
path1 = self.make_path("Beta")
self.os.rename(path0, path1)
- self.assertEqual(['beta'], sorted(self.os.listdir(path0)))
+ self.assertEqual(["beta"], sorted(self.os.listdir(path0)))
def test_rename_symlink_to_other_case_works_in_windows(self):
self.check_windows_only()
@@ -3326,134 +3401,160 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
path0 = self.make_path("beta", "Beta")
path1 = self.make_path("Beta")
self.os.rename(path0, path1)
- self.assertEqual(['Beta'], sorted(self.os.listdir(path0)))
+ self.assertEqual(["Beta"], sorted(self.os.listdir(path0)))
+
+ def test_renames_creates_missing_dirs(self):
+ old_path = self.make_path("foo.txt")
+ self.create_file(old_path)
+ new_path = self.make_path("new", "dir", "bar.txt")
+ self.os.renames(old_path, new_path)
+ self.assertTrue(self.os.path.exists(new_path))
+ self.assertFalse(self.os.path.exists(old_path))
+
+ def test_renames_removes_empty_dirs(self):
+ old_base_path = self.make_path("old")
+ old_path = self.make_path("old", "dir1", "dir2", "foo.txt")
+ other_file = self.os.path.join(old_base_path, "foo.png")
+ self.create_file(old_path)
+ self.create_file(other_file)
+ new_path = self.make_path("new", "bar.txt")
+ self.os.renames(old_path, new_path)
+ self.assertTrue(self.os.path.exists(new_path))
+ self.assertFalse(self.os.path.exists(old_path))
+ self.assertTrue(self.os.path.exists(old_base_path))
+ removed_path = self.os.path.join(old_base_path, "dir1")
+ self.assertFalse(self.os.path.exists(removed_path))
def test_stat_with_mixed_case(self):
# Regression test for #310
self.skip_if_symlink_not_supported()
- base_path = self.make_path('foo')
- path = self.os.path.join(base_path, 'bar')
+ base_path = self.make_path("foo")
+ path = self.os.path.join(base_path, "bar")
self.create_dir(path)
- path = self.os.path.join(path, 'Bar')
+ path = self.os.path.join(path, "Bar")
self.os.symlink(base_path, path)
- path = self.os.path.join(path, 'Bar')
+ path = self.os.path.join(path, "Bar")
# used to raise
self.os.stat(path)
def test_hardlink_works_with_symlink(self):
self.skip_if_symlink_not_supported()
- base_path = self.make_path('foo')
+ base_path = self.make_path("foo")
self.create_dir(base_path)
- symlink_path = self.os.path.join(base_path, 'slink')
+ symlink_path = self.os.path.join(base_path, "slink")
self.os.symlink(base_path.upper(), symlink_path)
- file_path = self.os.path.join(base_path, 'slink', 'beta')
+ file_path = self.os.path.join(base_path, "slink", "beta")
self.create_file(file_path)
- link_path = self.os.path.join(base_path, 'Slink', 'gamma')
+ link_path = self.os.path.join(base_path, "Slink", "gamma")
self.os.link(file_path, link_path)
self.assertTrue(self.os.path.exists(link_path))
def test_replace_existing_directory_should_raise_under_windows(self):
"""Renaming to an existing directory raises OSError under Windows."""
self.check_windows_only()
- old_path = self.make_path('foo', 'bar')
- new_path = self.make_path('foo', 'baz')
+ old_path = self.make_path("foo", "bar")
+ new_path = self.make_path("foo", "baz")
self.create_dir(old_path)
self.create_dir(new_path)
- self.assert_raises_os_error(errno.EACCES, self.os.replace, old_path,
- new_path.upper())
+ self.assert_raises_os_error(
+ errno.EACCES, self.os.replace, old_path, new_path.upper()
+ )
def test_rename_to_existing_directory_under_posix(self):
"""Renaming to an existing directory changes the existing directory
under Posix."""
self.check_posix_only()
- old_path = self.make_path('foo', 'bar')
- new_path = self.make_path('xyzzy')
- self.create_dir(self.os.path.join(old_path, 'sub'))
+ old_path = self.make_path("foo", "bar")
+ new_path = self.make_path("xyzzy")
+ self.create_dir(self.os.path.join(old_path, "sub"))
self.create_dir(new_path)
self.os.rename(old_path.upper(), new_path.upper())
- self.assertTrue(
- self.os.path.exists(self.os.path.join(new_path, 'sub')))
+ self.assertTrue(self.os.path.exists(self.os.path.join(new_path, "sub")))
self.assertFalse(self.os.path.exists(old_path))
def test_rename_file_to_existing_directory_raises_under_posix(self):
self.check_posix_only()
- file_path = self.make_path('foo', 'bar', 'baz')
- new_path = self.make_path('xyzzy')
+ file_path = self.make_path("foo", "bar", "baz")
+ new_path = self.make_path("xyzzy")
self.create_file(file_path)
self.create_dir(new_path)
- self.assert_raises_os_error(errno.EISDIR, self.os.rename,
- file_path.upper(),
- new_path.upper())
+ self.assert_raises_os_error(
+ errno.EISDIR, self.os.rename, file_path.upper(), new_path.upper()
+ )
def test_rename_to_existent_file_posix(self):
"""Can rename a file to a used name under Unix."""
self.check_posix_only()
- directory = self.make_path('xyzzy')
- old_file_path = self.os.path.join(directory, 'plugh_old')
- new_file_path = self.os.path.join(directory, 'plugh_new')
- self.create_file(old_file_path, contents='test contents 1')
- self.create_file(new_file_path, contents='test contents 2')
+ directory = self.make_path("xyzzy")
+ old_file_path = self.os.path.join(directory, "plugh_old")
+ new_file_path = self.os.path.join(directory, "plugh_new")
+ self.create_file(old_file_path, contents="test contents 1")
+ self.create_file(new_file_path, contents="test contents 2")
self.assertTrue(self.os.path.exists(old_file_path))
self.assertTrue(self.os.path.exists(new_file_path))
self.os.rename(old_file_path.upper(), new_file_path.upper())
self.assertFalse(self.os.path.exists(old_file_path))
self.assertTrue(self.os.path.exists(new_file_path))
- self.check_contents(new_file_path, 'test contents 1')
+ self.check_contents(new_file_path, "test contents 1")
def test_rename_to_existent_file_windows(self):
"""Renaming a file to a used name raises OSError under Windows."""
self.check_windows_only()
- directory = self.make_path('xyzzy')
- old_file_path = self.os.path.join(directory, 'plugh_old')
- new_file_path = self.os.path.join(directory, 'plugh_new')
- self.create_file(old_file_path, contents='test contents 1')
- self.create_file(new_file_path, contents='test contents 2')
+ directory = self.make_path("xyzzy")
+ old_file_path = self.os.path.join(directory, "plugh_old")
+ new_file_path = self.os.path.join(directory, "plugh_new")
+ self.create_file(old_file_path, contents="test contents 1")
+ self.create_file(new_file_path, contents="test contents 2")
self.assertTrue(self.os.path.exists(old_file_path))
self.assertTrue(self.os.path.exists(new_file_path))
- self.assert_raises_os_error(errno.EEXIST, self.os.rename,
- old_file_path.upper(),
- new_file_path.upper())
+ self.assert_raises_os_error(
+ errno.EEXIST,
+ self.os.rename,
+ old_file_path.upper(),
+ new_file_path.upper(),
+ )
def test_replace_to_existent_file(self):
"""Replaces an existing file (does not work with `rename()` under
Windows)."""
- directory = self.make_path('xyzzy')
- old_file_path = self.os.path.join(directory, 'plugh_old')
- new_file_path = self.os.path.join(directory, 'plugh_new')
- self.create_file(old_file_path, contents='test contents 1')
- self.create_file(new_file_path, contents='test contents 2')
+ directory = self.make_path("xyzzy")
+ old_file_path = self.os.path.join(directory, "plugh_old")
+ new_file_path = self.os.path.join(directory, "plugh_new")
+ self.create_file(old_file_path, contents="test contents 1")
+ self.create_file(new_file_path, contents="test contents 2")
self.assertTrue(self.os.path.exists(old_file_path))
self.assertTrue(self.os.path.exists(new_file_path))
self.os.replace(old_file_path.upper(), new_file_path.upper())
self.assertFalse(self.os.path.exists(old_file_path))
self.assertTrue(self.os.path.exists(new_file_path))
- self.check_contents(new_file_path, 'test contents 1')
+ self.check_contents(new_file_path, "test contents 1")
def test_rename_to_nonexistent_dir(self):
"""Can rename a file to a name in a nonexistent dir."""
- directory = self.make_path('xyzzy')
- old_file_path = self.os.path.join(directory, 'plugh_old')
- new_file_path = self.os.path.join(
- directory, 'no_such_path', 'plugh_new')
- self.create_file(old_file_path, contents='test contents')
+ directory = self.make_path("xyzzy")
+ old_file_path = self.os.path.join(directory, "plugh_old")
+ new_file_path = self.os.path.join(directory, "no_such_path", "plugh_new")
+ self.create_file(old_file_path, contents="test contents")
self.assertTrue(self.os.path.exists(old_file_path))
self.assertFalse(self.os.path.exists(new_file_path))
- self.assert_raises_os_error(errno.ENOENT, self.os.rename,
- old_file_path.upper(),
- new_file_path.upper())
+ self.assert_raises_os_error(
+ errno.ENOENT,
+ self.os.rename,
+ old_file_path.upper(),
+ new_file_path.upper(),
+ )
self.assertTrue(self.os.path.exists(old_file_path))
self.assertFalse(self.os.path.exists(new_file_path))
- self.check_contents(old_file_path, 'test contents')
+ self.check_contents(old_file_path, "test contents")
def check_rename_case_only_with_symlink_parent(self):
# Regression test for #319
- self.os.symlink(self.base_path, self.make_path('link'))
- dir_upper = self.make_path('link', 'Alpha')
+ self.os.symlink(self.base_path, self.make_path("link"))
+ dir_upper = self.make_path("link", "Alpha")
self.os.mkdir(dir_upper)
- dir_lower = self.make_path('alpha')
+ dir_lower = self.make_path("alpha")
self.os.rename(dir_upper, dir_lower)
- self.assertEqual(['alpha', 'link'],
- sorted(self.os.listdir(self.base_path)))
+ self.assertEqual(["alpha", "link"], sorted(self.os.listdir(self.base_path)))
def test_rename_case_only_with_symlink_parent_windows(self):
self.check_windows_only()
@@ -3466,13 +3567,13 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_rename_dir(self):
"""Test a rename of a directory."""
- directory = self.make_path('xyzzy')
- before_dir = self.os.path.join(directory, 'before')
- before_file = self.os.path.join(directory, 'before', 'file')
- after_dir = self.os.path.join(directory, 'after')
- after_file = self.os.path.join(directory, 'after', 'file')
+ directory = self.make_path("xyzzy")
+ before_dir = self.os.path.join(directory, "before")
+ before_file = self.os.path.join(directory, "before", "file")
+ after_dir = self.os.path.join(directory, "after")
+ after_file = self.os.path.join(directory, "after", "file")
self.create_dir(before_dir)
- self.create_file(before_file, contents='payload')
+ self.create_file(before_file, contents="payload")
self.assertTrue(self.os.path.exists(before_dir.upper()))
self.assertTrue(self.os.path.exists(before_file.upper()))
self.assertFalse(self.os.path.exists(after_dir.upper()))
@@ -3482,22 +3583,22 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
self.assertFalse(self.os.path.exists(before_file.upper()))
self.assertTrue(self.os.path.exists(after_dir.upper()))
self.assertTrue(self.os.path.exists(after_file.upper()))
- self.check_contents(after_file, 'payload')
+ self.check_contents(after_file, "payload")
def test_rename_same_filenames(self):
"""Test renaming when old and new names are the same."""
- directory = self.make_path('xyzzy')
- file_contents = 'Spam eggs'
- file_path = self.os.path.join(directory, 'eggs')
+ directory = self.make_path("xyzzy")
+ file_contents = "Spam eggs"
+ file_path = self.os.path.join(directory, "eggs")
self.create_file(file_path, contents=file_contents)
self.os.rename(file_path, file_path.upper())
self.check_contents(file_path, file_contents)
def test_rmdir(self):
"""Can remove a directory."""
- directory = self.make_path('xyzzy')
- sub_dir = self.make_path('xyzzy', 'abccd')
- other_dir = self.make_path('xyzzy', 'cdeed')
+ directory = self.make_path("xyzzy")
+ sub_dir = self.make_path("xyzzy", "abccd")
+ other_dir = self.make_path("xyzzy", "cdeed")
self.create_dir(directory)
self.assertTrue(self.os.path.exists(directory))
self.os.rmdir(directory)
@@ -3505,30 +3606,30 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
self.create_dir(sub_dir)
self.create_dir(other_dir)
self.os.chdir(sub_dir)
- self.os.rmdir('../CDEED')
+ self.os.rmdir("../CDEED")
self.assertFalse(self.os.path.exists(other_dir))
- self.os.chdir('..')
- self.os.rmdir('AbcCd')
+ self.os.chdir("..")
+ self.os.rmdir("AbcCd")
self.assertFalse(self.os.path.exists(sub_dir))
def test_rmdir_via_symlink(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- base_path = self.make_path('foo', 'bar')
- dir_path = self.os.path.join(base_path, 'alpha')
+ base_path = self.make_path("foo", "bar")
+ dir_path = self.os.path.join(base_path, "alpha")
self.create_dir(dir_path)
- link_path = self.os.path.join(base_path, 'beta')
+ link_path = self.os.path.join(base_path, "beta")
self.os.symlink(base_path, link_path)
- self.os.rmdir(link_path + '/Alpha')
+ self.os.rmdir(link_path + "/Alpha")
self.assertFalse(self.os.path.exists(dir_path))
def test_remove_dirs_with_non_top_symlink_succeeds(self):
self.check_posix_only()
- dir_path = self.make_path('dir')
- dir_link = self.make_path('dir_link')
+ dir_path = self.make_path("dir")
+ dir_link = self.make_path("dir_link")
self.create_dir(dir_path)
self.os.symlink(dir_path, dir_link)
- dir_in_dir = self.os.path.join(dir_link, 'dir2')
+ dir_in_dir = self.os.path.join(dir_link, "dir2")
self.create_dir(dir_in_dir)
self.os.removedirs(dir_in_dir.upper())
self.assertFalse(self.os.path.exists(dir_in_dir))
@@ -3537,9 +3638,9 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_mkdir_raises_on_symlink_in_posix(self):
self.check_posix_only()
- base_path = self.make_path('foo', 'bar')
- link_path = self.os.path.join(base_path, 'link_to_dir')
- dir_path = self.os.path.join(base_path, 'dir')
+ base_path = self.make_path("foo", "bar")
+ link_path = self.os.path.join(base_path, "link_to_dir")
+ dir_path = self.os.path.join(base_path, "dir")
self.create_dir(dir_path)
self.os.symlink(dir_path.upper(), link_path.upper())
self.assert_raises_os_error(errno.ENOTDIR, self.os.rmdir, link_path)
@@ -3547,9 +3648,9 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_mkdir_removes_symlink_in_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- base_path = self.make_path('foo', 'bar')
- link_path = self.os.path.join(base_path, 'link_to_dir')
- dir_path = self.os.path.join(base_path, 'dir')
+ base_path = self.make_path("foo", "bar")
+ link_path = self.os.path.join(base_path, "link_to_dir")
+ dir_path = self.os.path.join(base_path, "dir")
self.create_dir(dir_path)
self.os.symlink(dir_path.upper(), link_path.upper())
self.os.rmdir(link_path)
@@ -3558,37 +3659,37 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_mkdir_raises_if_directory_exists(self):
"""mkdir raises exception if directory already exists."""
- directory = self.make_path('xyzzy')
+ directory = self.make_path("xyzzy")
self.create_dir(directory)
self.assertTrue(self.os.path.exists(directory))
- self.assert_raises_os_error(errno.EEXIST,
- self.os.mkdir, directory.upper())
+ self.assert_raises_os_error(errno.EEXIST, self.os.mkdir, directory.upper())
def test_mkdir_raises_if_file_exists(self):
"""mkdir raises exception if name already exists as a file."""
- directory = self.make_path('xyzzy')
- file_path = self.os.path.join(directory, 'plugh')
+ directory = self.make_path("xyzzy")
+ file_path = self.os.path.join(directory, "plugh")
self.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path))
- self.assert_raises_os_error(errno.EEXIST,
- self.os.mkdir, file_path.upper())
+ self.assert_raises_os_error(errno.EEXIST, self.os.mkdir, file_path.upper())
def test_mkdir_raises_if_symlink_exists(self):
# Regression test for #309
self.skip_if_symlink_not_supported()
- path1 = self.make_path('baz')
+ path1 = self.make_path("baz")
self.os.symlink(path1, path1)
- path2 = self.make_path('Baz')
+ path2 = self.make_path("Baz")
self.assert_raises_os_error(errno.EEXIST, self.os.mkdir, path2)
def check_mkdir_raises_if_parent_is_file(self, error_type):
"""mkdir raises exception if name already exists as a file."""
- directory = self.make_path('xyzzy')
- file_path = self.os.path.join(directory, 'plugh')
+ directory = self.make_path("xyzzy")
+ file_path = self.os.path.join(directory, "plugh")
self.create_file(file_path)
- self.assert_raises_os_error(error_type, self.os.mkdir,
- self.os.path.join(file_path.upper(),
- 'ff'))
+ self.assert_raises_os_error(
+ error_type,
+ self.os.mkdir,
+ self.os.path.join(file_path.upper(), "ff"),
+ )
def test_mkdir_raises_if_parent_is_file_posix(self):
self.check_posix_only()
@@ -3600,20 +3701,19 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_makedirs(self):
"""makedirs can create a directory even if parent does not exist."""
- parent = self.make_path('xyzzy')
- directory = self.os.path.join(parent, 'foo')
+ parent = self.make_path("xyzzy")
+ directory = self.os.path.join(parent, "foo")
self.assertFalse(self.os.path.exists(parent))
self.os.makedirs(directory.upper())
self.assertTrue(self.os.path.exists(directory))
def check_makedirs_raises_if_parent_is_file(self, error_type):
"""makedirs raises exception if a parent component exists as a file."""
- file_path = self.make_path('xyzzy')
- directory = self.os.path.join(file_path, 'plugh')
+ file_path = self.make_path("xyzzy")
+ directory = self.os.path.join(file_path, "plugh")
self.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path))
- self.assert_raises_os_error(error_type, self.os.makedirs,
- directory.upper())
+ self.assert_raises_os_error(error_type, self.os.makedirs, directory.upper())
def test_makedirs_raises_if_parent_is_file_posix(self):
self.check_posix_only()
@@ -3625,28 +3725,29 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_makedirs_raises_if_parent_is_broken_link(self):
self.check_posix_only()
- link_path = self.make_path('broken_link')
- self.os.symlink(self.make_path('bogus'), link_path)
- self.assert_raises_os_error(errno.ENOENT, self.os.makedirs,
- self.os.path.join(link_path.upper(),
- 'newdir'))
+ link_path = self.make_path("broken_link")
+ self.os.symlink(self.make_path("bogus"), link_path)
+ self.assert_raises_os_error(
+ errno.ENOENT,
+ self.os.makedirs,
+ self.os.path.join(link_path.upper(), "newdir"),
+ )
def test_makedirs_exist_ok(self):
"""makedirs uses the exist_ok argument"""
- directory = self.make_path('xyzzy', 'foo')
+ directory = self.make_path("xyzzy", "foo")
self.create_dir(directory)
self.assertTrue(self.os.path.exists(directory))
- self.assert_raises_os_error(errno.EEXIST, self.os.makedirs,
- directory.upper())
+ self.assert_raises_os_error(errno.EEXIST, self.os.makedirs, directory.upper())
self.os.makedirs(directory.upper(), exist_ok=True)
self.assertTrue(self.os.path.exists(directory))
# test fsync and fdatasync
def test_fsync_pass(self):
- test_file_path = self.make_path('test_file')
- self.create_file(test_file_path, contents='dummy file contents')
- test_file = self.open(test_file_path.upper(), 'r+')
+ test_file_path = self.make_path("test_file")
+ self.create_file(test_file_path, contents="dummy file contents")
+ test_file = self.open(test_file_path.upper(), "r+")
test_fd = test_file.fileno()
# Test that this doesn't raise anything
self.os.fsync(test_fd)
@@ -3658,7 +3759,7 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
# set up
self.check_posix_only()
self.skip_real_fs()
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
# actual tests
self.os.chmod(path.upper(), 0o6543)
@@ -3669,12 +3770,12 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_symlink(self):
self.skip_if_symlink_not_supported()
- file_path = self.make_path('foo', 'bar', 'baz')
- self.create_dir(self.make_path('foo', 'bar'))
- self.os.symlink('bogus', file_path.upper())
+ file_path = self.make_path("foo", "bar", "baz")
+ self.create_dir(self.make_path("foo", "bar"))
+ self.os.symlink("bogus", file_path.upper())
self.assertTrue(self.os.path.lexists(file_path))
self.assertFalse(self.os.path.exists(file_path))
- self.create_file(self.make_path('Foo', 'Bar', 'Bogus'))
+ self.create_file(self.make_path("Foo", "Bar", "Bogus"))
self.assertTrue(self.os.path.lexists(file_path))
self.assertTrue(self.os.path.exists(file_path))
@@ -3682,9 +3783,9 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_link_delete(self):
self.skip_if_symlink_not_supported()
- file1_path = self.make_path('test_file1')
- file2_path = self.make_path('test_file2')
- contents1 = 'abcdef'
+ file1_path = self.make_path("test_file1")
+ file2_path = self.make_path("test_file2")
+ contents1 = "abcdef"
# Create file
self.create_file(file1_path, contents=contents1)
# link to second file
@@ -3698,30 +3799,30 @@ class FakeOsModuleTestCaseInsensitiveFS(FakeOsModuleTestBase):
def test_link_is_existing_file(self):
self.skip_if_symlink_not_supported()
- file_path = self.make_path('foo', 'bar')
+ file_path = self.make_path("foo", "bar")
self.create_file(file_path)
- self.assert_raises_os_error(errno.EEXIST, self.os.link,
- file_path.upper(), file_path.upper())
+ self.assert_raises_os_error(
+ errno.EEXIST, self.os.link, file_path.upper(), file_path.upper()
+ )
def test_link_is_broken_symlink(self):
# Regression test for #311
self.skip_if_symlink_not_supported()
self.check_case_insensitive_fs()
- file_path = self.make_path('baz')
+ file_path = self.make_path("baz")
self.create_file(file_path)
- path_lower = self.make_path('foo')
+ path_lower = self.make_path("foo")
self.os.symlink(path_lower, path_lower)
- path_upper = self.make_path('Foo')
- self.assert_raises_os_error(errno.EEXIST,
- self.os.link, file_path, path_upper)
+ path_upper = self.make_path("Foo")
+ self.assert_raises_os_error(errno.EEXIST, self.os.link, file_path, path_upper)
def test_link_with_changed_case(self):
# Regression test for #312
self.skip_if_symlink_not_supported()
self.check_case_insensitive_fs()
- link_path = self.make_path('link')
+ link_path = self.make_path("link")
self.os.symlink(self.base_path, link_path)
- link_path = self.os.path.join(link_path, 'Link')
+ link_path = self.os.path.join(link_path, "Link")
self.assertTrue(self.os.lstat(link_path))
@@ -3733,7 +3834,7 @@ class RealOsModuleTestCaseInsensitiveFS(FakeOsModuleTestCaseInsensitiveFS):
class FakeOsModuleTimeTest(FakeOsModuleTestBase):
def test_chmod_st_ctime(self):
with self.mock_time(start=200):
- file_path = 'some_file'
+ file_path = "some_file"
self.filesystem.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path))
@@ -3745,7 +3846,7 @@ class FakeOsModuleTimeTest(FakeOsModuleTestBase):
self.assertEqual(220, st.st_ctime)
def test_utime_sets_current_time_if_args_is_none(self):
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
with self.mock_time(start=200):
@@ -3754,88 +3855,9 @@ class FakeOsModuleTimeTest(FakeOsModuleTestBase):
self.assertEqual(200, st.st_atime)
self.assertEqual(200, st.st_mtime)
- def test_utime_sets_current_time_if_args_is_none_with_floats(self):
- # we set os.stat_float_times() to False, so atime/ctime/mtime
- # are converted as ints (seconds since epoch)
- stat_float_times = fake_filesystem.FakeOsModule.stat_float_times()
- fake_filesystem.FakeOsModule.stat_float_times(False)
- try:
- with self.mock_time(start=200.9124):
- path = '/some_file'
- self.createTestFile(path)
-
- st = self.os.stat(path)
- # 200 is the current time established above
- # (if converted to int)
- self.assertEqual(200, st.st_atime)
- self.assertTrue(isinstance(st.st_atime, int))
- self.assertEqual(220, st.st_mtime)
- self.assertTrue(isinstance(st.st_mtime, int))
-
- self.assertEqual(200912400000, st.st_atime_ns)
- self.assertEqual(220912400000, st.st_mtime_ns)
-
- self.assertEqual(220, st.st_mtime)
- self.assertEqual(240, st.st_ctime)
- # actual tests
- self.os.utime(path, times=None)
- st = self.os.stat(path)
- self.assertEqual(260, st.st_atime)
- self.assertTrue(isinstance(st.st_atime, int))
- self.assertEqual(260, st.st_mtime)
- self.assertTrue(isinstance(st.st_mtime, int))
- self.assertEqual(260912400000, st.st_atime_ns)
- self.assertEqual(260912400000, st.st_mtime_ns)
- finally:
- fake_filesystem.FakeOsModule.stat_float_times(stat_float_times)
-
- def test_utime_sets_current_time_if_args_is_none_with_floats_n_sec(self):
- stat_float_times = fake_filesystem.FakeOsModule.stat_float_times()
- fake_filesystem.FakeOsModule.stat_float_times(False)
- try:
- with self.mock_time(start=200.9123):
- path = self.make_path('some_file')
- self.createTestFile(path)
- test_file = self.filesystem.get_object(path)
-
- st = self.os.stat(path)
- self.assertEqual(200, st.st_atime)
- self.assertEqual(220, st.st_mtime)
- self.assertEqual(240, st.st_ctime)
- self.assertEqual(240, test_file.st_ctime)
- self.assertTrue(isinstance(st.st_ctime, int))
- self.assertTrue(isinstance(test_file.st_ctime, int))
-
- self.os.stat_float_times(True) # first time float time
- self.assertEqual(240, st.st_ctime) # st does not change
- self.assertEqual(240.9123, test_file.st_ctime) # but the file
- self.assertTrue(isinstance(st.st_ctime, int))
- self.assertTrue(isinstance(test_file.st_ctime, float))
-
- self.os.stat_float_times(False) # reverting to int
- self.assertEqual(240, test_file.st_ctime)
- self.assertTrue(isinstance(test_file.st_ctime, int))
-
- self.assertEqual(240, st.st_ctime)
- self.assertTrue(isinstance(st.st_ctime, int))
-
- self.os.stat_float_times(True)
- st = self.os.stat(path)
- # float time not converted to int
- self.assertAlmostEqual(200.9123, st.st_atime)
- self.assertAlmostEqual(220.9123, st.st_mtime)
- self.assertAlmostEqual(240.9123, test_file.st_ctime,
- st.st_ctime)
- self.os.utime(path, times=None)
- st = self.os.stat(path)
- self.assertAlmostEqual(260.9123, st.st_atime)
- self.assertAlmostEqual(260.9123, st.st_mtime)
- finally:
- fake_filesystem.FakeOsModule.stat_float_times(stat_float_times)
-
def test_utime_sets_specified_time(self):
# set up
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
self.os.stat(path)
# actual tests
@@ -3846,7 +3868,7 @@ class FakeOsModuleTimeTest(FakeOsModuleTestBase):
def test_utime_dir(self):
# set up
- path = '/some_dir'
+ path = "/some_dir"
self.createTestDirectory(path)
# actual tests
self.os.utime(path, times=(1.0, 2.0))
@@ -3855,9 +3877,9 @@ class FakeOsModuleTimeTest(FakeOsModuleTestBase):
self.assertEqual(2.0, st.st_mtime)
def test_utime_follow_symlinks(self):
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
- link_path = '/link_to_some_file'
+ link_path = "/link_to_some_file"
self.filesystem.create_symlink(link_path, path)
self.os.utime(link_path, times=(1, 2))
@@ -3866,9 +3888,9 @@ class FakeOsModuleTimeTest(FakeOsModuleTestBase):
self.assertEqual(2, st.st_mtime)
def test_utime_no_follow_symlinks(self):
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
- link_path = '/link_to_some_file'
+ link_path = "/link_to_some_file"
self.filesystem.create_symlink(link_path, path)
self.os.utime(link_path, times=(1, 2), follow_symlinks=False)
@@ -3880,22 +3902,22 @@ class FakeOsModuleTimeTest(FakeOsModuleTestBase):
self.assertEqual(2, st.st_mtime)
def test_utime_non_existent(self):
- path = '/non/existent/file'
+ path = "/non/existent/file"
self.assertFalse(self.os.path.exists(path))
self.assert_raises_os_error(errno.ENOENT, self.os.utime, path, (1, 2))
def test_utime_invalid_times_arg_raises(self):
- path = '/some_dir'
+ path = "/some_dir"
self.createTestDirectory(path)
# the error message differs with different Python versions
# we don't expect the same message here
self.assertRaises(TypeError, self.os.utime, path, (1, 2, 3))
- self.assertRaises(TypeError, self.os.utime, path, (1, 'str'))
+ self.assertRaises(TypeError, self.os.utime, path, (1, "str"))
def test_utime_sets_specified_time_in_ns(self):
# set up
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
self.os.stat(path)
@@ -3906,19 +3928,20 @@ class FakeOsModuleTimeTest(FakeOsModuleTestBase):
self.assertEqual(0.4, st.st_mtime)
def test_utime_incorrect_ns_argument_raises(self):
- file_path = 'some_file'
+ file_path = "some_file"
self.filesystem.create_file(file_path)
self.assertRaises(TypeError, self.os.utime, file_path, ns=200000000)
- self.assertRaises(TypeError, self.os.utime, file_path, ns=('a', 'b'))
- self.assertRaises(ValueError, self.os.utime, file_path, times=(1, 2),
- ns=(100, 200))
+ self.assertRaises(TypeError, self.os.utime, file_path, ns=("a", "b"))
+ self.assertRaises(
+ ValueError, self.os.utime, file_path, times=(1, 2), ns=(100, 200)
+ )
def test_utime_uses_open_fd_as_path(self):
if os.utime not in os.supports_fd:
self.skip_real_fs()
self.assert_raises_os_error(errno.EBADF, self.os.utime, 5, (1, 2))
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.createTestFile(path)
with FakeFileOpen(self.filesystem)(path) as f:
@@ -3936,47 +3959,45 @@ class FakeOsModuleLowLevelFileOpTest(FakeOsModuleTestBase):
super(FakeOsModuleLowLevelFileOpTest, self).setUp()
def test_open_read_only(self):
- file_path = self.make_path('file1')
- self.create_file(file_path, contents=b'contents')
+ file_path = self.make_path("file1")
+ self.create_file(file_path, contents=b"contents")
file_des = self.os.open(file_path, os.O_RDONLY)
- self.assertEqual(b'contents', self.os.read(file_des, 8))
- self.assert_raises_os_error(errno.EBADF,
- self.os.write, file_des, b'test')
+ self.assertEqual(b"contents", self.os.read(file_des, 8))
+ self.assert_raises_os_error(errno.EBADF, self.os.write, file_des, b"test")
self.os.close(file_des)
def test_open_read_only_write_zero_bytes_posix(self):
self.check_posix_only()
- file_path = self.make_path('file1')
- self.create_file(file_path, contents=b'contents')
+ file_path = self.make_path("file1")
+ self.create_file(file_path, contents=b"contents")
file_des = self.os.open(file_path, os.O_RDONLY)
- self.assert_raises_os_error(errno.EBADF,
- self.os.write, file_des, b'test')
+ self.assert_raises_os_error(errno.EBADF, self.os.write, file_des, b"test")
self.os.close(file_des)
def test_open_read_only_write_zero_bytes_windows(self):
# under Windows, writing an empty string to a read only file
# is not an error
self.check_windows_only()
- file_path = self.make_path('file1')
- self.create_file(file_path, contents=b'contents')
+ file_path = self.make_path("file1")
+ self.create_file(file_path, contents=b"contents")
file_des = self.os.open(file_path, os.O_RDONLY)
- self.assertEqual(0, self.os.write(file_des, b''))
+ self.assertEqual(0, self.os.write(file_des, b""))
self.os.close(file_des)
def test_open_write_only(self):
- file_path = self.make_path('file1')
- self.create_file(file_path, contents=b'contents')
+ file_path = self.make_path("file1")
+ self.create_file(file_path, contents=b"contents")
file_des = self.os.open(file_path, os.O_WRONLY)
- self.assertEqual(4, self.os.write(file_des, b'test'))
- self.check_contents(file_path, b'testents')
+ self.assertEqual(4, self.os.write(file_des, b"test"))
+ self.check_contents(file_path, b"testents")
self.os.close(file_des)
def test_open_write_only_raises_on_read(self):
- file_path = self.make_path('file1')
- self.create_file(file_path, contents=b'contents')
+ file_path = self.make_path("file1")
+ self.create_file(file_path, contents=b"contents")
file_des = self.os.open(file_path, os.O_WRONLY)
self.assert_raises_os_error(errno.EBADF, self.os.read, file_des, 5)
@@ -3984,18 +4005,17 @@ class FakeOsModuleLowLevelFileOpTest(FakeOsModuleTestBase):
file_des = self.os.open(file_path, os.O_WRONLY | os.O_TRUNC)
self.assert_raises_os_error(errno.EBADF, self.os.read, file_des, 5)
self.os.close(file_des)
- file_path2 = self.make_path('file2')
+ file_path2 = self.make_path("file2")
file_des = self.os.open(file_path2, os.O_CREAT | os.O_WRONLY)
self.assert_raises_os_error(errno.EBADF, self.os.read, file_des, 5)
self.os.close(file_des)
- file_des = self.os.open(file_path2,
- os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
+ file_des = self.os.open(file_path2, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
self.assert_raises_os_error(errno.EBADF, self.os.read, file_des, 5)
self.os.close(file_des)
def test_open_write_only_read_zero_bytes_posix(self):
self.check_posix_only()
- file_path = self.make_path('file1')
+ file_path = self.make_path("file1")
file_des = self.os.open(file_path, os.O_CREAT | os.O_WRONLY)
self.assert_raises_os_error(errno.EBADF, self.os.read, file_des, 0)
self.os.close(file_des)
@@ -4003,129 +4023,135 @@ class FakeOsModuleLowLevelFileOpTest(FakeOsModuleTestBase):
def test_open_write_only_read_zero_bytes_windows(self):
# under Windows, reading 0 bytes from a write only file is not an error
self.check_windows_only()
- file_path = self.make_path('file1')
+ file_path = self.make_path("file1")
file_des = self.os.open(file_path, os.O_CREAT | os.O_WRONLY)
- self.assertEqual(b'', self.os.read(file_des, 0))
+ self.assertEqual(b"", self.os.read(file_des, 0))
self.os.close(file_des)
def test_open_read_write(self):
- file_path = self.make_path('file1')
- self.create_file(file_path, contents=b'contents')
+ file_path = self.make_path("file1")
+ self.create_file(file_path, contents=b"contents")
file_des = self.os.open(file_path, os.O_RDWR)
- self.assertEqual(4, self.os.write(file_des, b'test'))
- self.check_contents(file_path, b'testents')
+ self.assertEqual(4, self.os.write(file_des, b"test"))
+ self.check_contents(file_path, b"testents")
self.os.close(file_des)
def test_open_create_is_read_only(self):
- file_path = self.make_path('file1')
+ file_path = self.make_path("file1")
file_des = self.os.open(file_path, os.O_CREAT)
- self.assertEqual(b'', self.os.read(file_des, 1))
- self.assert_raises_os_error(errno.EBADF,
- self.os.write, file_des, b'foo')
+ self.assertEqual(b"", self.os.read(file_des, 1))
+ self.assert_raises_os_error(errno.EBADF, self.os.write, file_des, b"foo")
self.os.close(file_des)
def test_open_create_truncate_is_read_only(self):
- file_path = self.make_path('file1')
+ file_path = self.make_path("file1")
file_des = self.os.open(file_path, os.O_CREAT | os.O_TRUNC)
- self.assertEqual(b'', self.os.read(file_des, 1))
- self.assert_raises_os_error(errno.EBADF,
- self.os.write, file_des, b'foo')
+ self.assertEqual(b"", self.os.read(file_des, 1))
+ self.assert_raises_os_error(errno.EBADF, self.os.write, file_des, b"foo")
self.os.close(file_des)
def test_open_raises_if_does_not_exist(self):
- file_path = self.make_path('file1')
- self.assert_raises_os_error(errno.ENOENT, self.os.open, file_path,
- os.O_RDONLY)
- self.assert_raises_os_error(errno.ENOENT, self.os.open, file_path,
- os.O_WRONLY)
- self.assert_raises_os_error(errno.ENOENT, self.os.open, file_path,
- os.O_RDWR)
+ file_path = self.make_path("file1")
+ self.assert_raises_os_error(errno.ENOENT, self.os.open, file_path, os.O_RDONLY)
+ self.assert_raises_os_error(errno.ENOENT, self.os.open, file_path, os.O_WRONLY)
+ self.assert_raises_os_error(errno.ENOENT, self.os.open, file_path, os.O_RDWR)
def test_exclusive_open_raises_without_create_mode(self):
self.skip_real_fs()
- file_path = self.make_path('file1')
- self.assertRaises(NotImplementedError, self.os.open, file_path,
- os.O_EXCL)
- self.assertRaises(NotImplementedError, self.os.open, file_path,
- os.O_EXCL | os.O_WRONLY)
- self.assertRaises(NotImplementedError, self.os.open, file_path,
- os.O_EXCL | os.O_RDWR)
- self.assertRaises(NotImplementedError, self.os.open, file_path,
- os.O_EXCL | os.O_TRUNC | os.O_APPEND)
+ file_path = self.make_path("file1")
+ self.assertRaises(NotImplementedError, self.os.open, file_path, os.O_EXCL)
+ self.assertRaises(
+ NotImplementedError,
+ self.os.open,
+ file_path,
+ os.O_EXCL | os.O_WRONLY,
+ )
+ self.assertRaises(
+ NotImplementedError, self.os.open, file_path, os.O_EXCL | os.O_RDWR
+ )
+ self.assertRaises(
+ NotImplementedError,
+ self.os.open,
+ file_path,
+ os.O_EXCL | os.O_TRUNC | os.O_APPEND,
+ )
def test_open_raises_if_parent_does_not_exist(self):
- path = self.make_path('alpha', 'alpha')
- self.assert_raises_os_error(errno.ENOENT, self.os.open, path,
- os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
+ path = self.make_path("alpha", "alpha")
+ self.assert_raises_os_error(
+ errno.ENOENT,
+ self.os.open,
+ path,
+ os.O_CREAT | os.O_WRONLY | os.O_TRUNC,
+ )
def test_open_truncate(self):
- file_path = self.make_path('file1')
- self.create_file(file_path, contents=b'contents')
+ file_path = self.make_path("file1")
+ self.create_file(file_path, contents=b"contents")
file_des = self.os.open(file_path, os.O_RDWR | os.O_TRUNC)
- self.assertEqual(b'', self.os.read(file_des, 8))
- self.assertEqual(4, self.os.write(file_des, b'test'))
- self.check_contents(file_path, b'test')
+ self.assertEqual(b"", self.os.read(file_des, 8))
+ self.assertEqual(4, self.os.write(file_des, b"test"))
+ self.check_contents(file_path, b"test")
self.os.close(file_des)
- @unittest.skipIf(not TestCase.is_windows,
- 'O_TEMPORARY only present in Windows')
+ @unittest.skipIf(not TestCase.is_windows, "O_TEMPORARY only present in Windows")
def test_temp_file(self):
- file_path = self.make_path('file1')
+ file_path = self.make_path("file1")
fd = self.os.open(file_path, os.O_CREAT | os.O_RDWR | os.O_TEMPORARY)
self.assertTrue(self.os.path.exists(file_path))
self.os.close(fd)
self.assertFalse(self.os.path.exists(file_path))
def test_open_append(self):
- file_path = self.make_path('file1')
- self.create_file(file_path, contents=b'contents')
+ file_path = self.make_path("file1")
+ self.create_file(file_path, contents=b"contents")
file_des = self.os.open(file_path, os.O_WRONLY | os.O_APPEND)
- self.assertEqual(4, self.os.write(file_des, b'test'))
- self.check_contents(file_path, b'contentstest')
+ self.assertEqual(4, self.os.write(file_des, b"test"))
+ self.check_contents(file_path, b"contentstest")
self.os.close(file_des)
def test_open_create(self):
- file_path = self.make_path('file1')
+ file_path = self.make_path("file1")
file_des = self.os.open(file_path, os.O_RDWR | os.O_CREAT)
self.assertTrue(self.os.path.exists(file_path))
- self.assertEqual(4, self.os.write(file_des, b'test'))
- self.check_contents(file_path, 'test')
+ self.assertEqual(4, self.os.write(file_des, b"test"))
+ self.check_contents(file_path, "test")
self.os.close(file_des)
def test_can_read_after_create_exclusive(self):
self.check_posix_only()
- path1 = self.make_path('alpha')
+ path1 = self.make_path("alpha")
file_des = self.os.open(path1, os.O_CREAT | os.O_EXCL)
- self.assertEqual(b'', self.os.read(file_des, 0))
- self.assert_raises_os_error(errno.EBADF, self.os.write, file_des, b'')
+ self.assertEqual(b"", self.os.read(file_des, 0))
+ self.assert_raises_os_error(errno.EBADF, self.os.write, file_des, b"")
self.os.close(file_des)
def test_open_create_mode_posix(self):
self.check_posix_only()
- file_path = self.make_path('file1')
+ file_path = self.make_path("file1")
file_des = self.os.open(file_path, os.O_WRONLY | os.O_CREAT, 0o700)
self.assertTrue(self.os.path.exists(file_path))
self.assert_raises_os_error(errno.EBADF, self.os.read, file_des, 5)
- self.assertEqual(4, self.os.write(file_des, b'test'))
+ self.assertEqual(4, self.os.write(file_des, b"test"))
self.assert_mode_equal(0o700, self.os.stat(file_path).st_mode)
self.os.close(file_des)
def test_open_create_mode_windows(self):
self.check_windows_only()
- file_path = self.make_path('file1')
+ file_path = self.make_path("file1")
file_des = self.os.open(file_path, os.O_WRONLY | os.O_CREAT, 0o700)
self.assertTrue(self.os.path.exists(file_path))
self.assert_raises_os_error(errno.EBADF, self.os.read, file_des, 5)
- self.assertEqual(4, self.os.write(file_des, b'test'))
+ self.assertEqual(4, self.os.write(file_des, b"test"))
self.assert_mode_equal(0o666, self.os.stat(file_path).st_mode)
self.os.close(file_des)
def testOpenCreateMode444Windows(self):
self.check_windows_only()
- file_path = self.make_path('file1')
+ file_path = self.make_path("file1")
file_des = self.os.open(file_path, os.O_WRONLY | os.O_CREAT, 0o442)
self.assert_mode_equal(0o444, self.os.stat(file_path).st_mode)
self.os.close(file_des)
@@ -4133,68 +4159,73 @@ class FakeOsModuleLowLevelFileOpTest(FakeOsModuleTestBase):
def testOpenCreateMode666Windows(self):
self.check_windows_only()
- file_path = self.make_path('file1')
+ file_path = self.make_path("file1")
file_des = self.os.open(file_path, os.O_WRONLY | os.O_CREAT, 0o224)
self.assert_mode_equal(0o666, self.os.stat(file_path).st_mode)
self.os.close(file_des)
def test_open_exclusive(self):
- file_path = self.make_path('file1')
+ file_path = self.make_path("file1")
file_des = self.os.open(file_path, os.O_RDWR | os.O_EXCL | os.O_CREAT)
self.assertTrue(self.os.path.exists(file_path))
self.os.close(file_des)
def test_open_exclusive_raises_if_file_exists(self):
- file_path = self.make_path('file1')
- self.create_file(file_path, contents=b'contents')
- self.assert_raises_os_error(errno.EEXIST, self.os.open, file_path,
- os.O_RDWR | os.O_EXCL | os.O_CREAT)
- self.assert_raises_os_error(errno.EEXIST, self.os.open, file_path,
- os.O_RDWR | os.O_EXCL | os.O_CREAT)
+ file_path = self.make_path("file1")
+ self.create_file(file_path, contents=b"contents")
+ self.assert_raises_os_error(
+ errno.EEXIST,
+ self.os.open,
+ file_path,
+ os.O_RDWR | os.O_EXCL | os.O_CREAT,
+ )
+ self.assert_raises_os_error(
+ errno.EEXIST,
+ self.os.open,
+ file_path,
+ os.O_RDWR | os.O_EXCL | os.O_CREAT,
+ )
def test_open_exclusive_raises_if_symlink_exists_in_posix(self):
self.check_posix_only()
- link_path = self.make_path('link')
- link_target = self.make_path('link_target')
+ link_path = self.make_path("link")
+ link_target = self.make_path("link_target")
self.os.symlink(link_target, link_path)
self.assert_raises_os_error(
- errno.EEXIST, self.os.open, link_path,
- os.O_CREAT | os.O_WRONLY | os.O_TRUNC | os.O_EXCL)
+ errno.EEXIST,
+ self.os.open,
+ link_path,
+ os.O_CREAT | os.O_WRONLY | os.O_TRUNC | os.O_EXCL,
+ )
def test_open_exclusive_if_symlink_exists_works_in_windows(self):
self.check_windows_only()
self.skip_if_symlink_not_supported()
- link_path = self.make_path('link')
- link_target = self.make_path('link_target')
+ link_path = self.make_path("link")
+ link_target = self.make_path("link_target")
self.os.symlink(link_target, link_path)
- fd = self.os.open(link_path,
- os.O_CREAT | os.O_WRONLY | os.O_TRUNC | os.O_EXCL)
+ fd = self.os.open(link_path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC | os.O_EXCL)
self.os.close(fd)
def test_open_directory_raises_under_windows(self):
self.check_windows_only()
- dir_path = self.make_path('dir')
+ dir_path = self.make_path("dir")
self.create_dir(dir_path)
- self.assert_raises_os_error(errno.EACCES, self.os.open, dir_path,
- os.O_RDONLY)
- self.assert_raises_os_error(errno.EACCES, self.os.open, dir_path,
- os.O_WRONLY)
- self.assert_raises_os_error(errno.EACCES, self.os.open, dir_path,
- os.O_RDWR)
+ self.assert_raises_os_error(errno.EACCES, self.os.open, dir_path, os.O_RDONLY)
+ self.assert_raises_os_error(errno.EACCES, self.os.open, dir_path, os.O_WRONLY)
+ self.assert_raises_os_error(errno.EACCES, self.os.open, dir_path, os.O_RDWR)
def test_open_directory_for_writing_raises_under_posix(self):
self.check_posix_only()
- dir_path = self.make_path('dir')
+ dir_path = self.make_path("dir")
self.create_dir(dir_path)
- self.assert_raises_os_error(errno.EISDIR, self.os.open, dir_path,
- os.O_WRONLY)
- self.assert_raises_os_error(errno.EISDIR, self.os.open, dir_path,
- os.O_RDWR)
+ self.assert_raises_os_error(errno.EISDIR, self.os.open, dir_path, os.O_WRONLY)
+ self.assert_raises_os_error(errno.EISDIR, self.os.open, dir_path, os.O_RDWR)
def test_open_directory_read_only_under_posix(self):
self.check_posix_only()
self.skip_real_fs()
- dir_path = self.make_path('dir')
+ dir_path = self.make_path("dir")
self.create_dir(dir_path)
file_des = self.os.open(dir_path, os.O_RDONLY)
self.assertEqual(3, file_des)
@@ -4204,29 +4235,26 @@ class FakeOsModuleLowLevelFileOpTest(FakeOsModuleTestBase):
self.check_linux_only()
dir_path = self.make_path("alpha")
self.os.mkdir(dir_path)
- self.assert_raises_os_error(errno.EISDIR,
- self.os.open, dir_path, os.O_CREAT)
+ self.assert_raises_os_error(errno.EISDIR, self.os.open, dir_path, os.O_CREAT)
def test_writing_to_existing_directory(self):
self.check_macos_only()
dir_path = self.make_path("alpha")
self.os.mkdir(dir_path)
fd = self.os.open(dir_path, os.O_CREAT)
- self.assert_raises_os_error(errno.EBADF, self.os.write, fd, b'')
+ self.assert_raises_os_error(errno.EBADF, self.os.write, fd, b"")
def test_opening_existing_directory_in_write_mode(self):
self.check_posix_only()
dir_path = self.make_path("alpha")
self.os.mkdir(dir_path)
- self.assert_raises_os_error(errno.EISDIR,
- self.os.open, dir_path, os.O_WRONLY)
+ self.assert_raises_os_error(errno.EISDIR, self.os.open, dir_path, os.O_WRONLY)
def test_open_mode_posix(self):
self.check_posix_only()
self.skip_real_fs()
- file_path = self.make_path('baz')
- file_des = self.os.open(file_path,
- os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
+ file_path = self.make_path("baz")
+ file_des = self.os.open(file_path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
stat0 = self.os.fstat(file_des)
# not a really good test as this replicates the code,
# but we don't know the umask at the test system
@@ -4235,103 +4263,104 @@ class FakeOsModuleLowLevelFileOpTest(FakeOsModuleTestBase):
def test_open_mode_windows(self):
self.check_windows_only()
- file_path = self.make_path('baz')
- file_des = self.os.open(file_path,
- os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
+ file_path = self.make_path("baz")
+ file_des = self.os.open(file_path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
stat0 = self.os.fstat(file_des)
self.assertEqual(0o100666, stat0.st_mode)
self.os.close(file_des)
def test_write_read(self):
- file_path = self.make_path('file1')
- self.create_file(file_path, contents=b'orig contents')
- new_contents = b'1234567890abcdef'
+ file_path = self.make_path("file1")
+ self.create_file(file_path, contents=b"orig contents")
+ new_contents = b"1234567890abcdef"
- with self.open(file_path, 'wb') as fh:
+ with self.open(file_path, "wb") as fh:
fileno = fh.fileno()
- self.assertEqual(len(new_contents),
- self.os.write(fileno, new_contents))
+ self.assertEqual(len(new_contents), self.os.write(fileno, new_contents))
self.check_contents(file_path, new_contents)
- with self.open(file_path, 'rb') as fh:
+ with self.open(file_path, "rb") as fh:
fileno = fh.fileno()
- self.assertEqual(b'', self.os.read(fileno, 0))
+ self.assertEqual(b"", self.os.read(fileno, 0))
self.assertEqual(new_contents[0:2], self.os.read(fileno, 2))
self.assertEqual(new_contents[2:10], self.os.read(fileno, 8))
self.assertEqual(new_contents[10:], self.os.read(fileno, 100))
- self.assertEqual(b'', self.os.read(fileno, 10))
+ self.assertEqual(b"", self.os.read(fileno, 10))
- self.assert_raises_os_error(errno.EBADF, self.os.write, fileno,
- new_contents)
+ self.assert_raises_os_error(errno.EBADF, self.os.write, fileno, new_contents)
self.assert_raises_os_error(errno.EBADF, self.os.read, fileno, 10)
def test_write_from_different_f_ds(self):
# Regression test for #211
- file_path = self.make_path('baz')
+ file_path = self.make_path("baz")
fd0 = self.os.open(file_path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
fd1 = self.os.open(file_path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
- self.os.write(fd0, b'aaaa')
- self.os.write(fd1, b'bb')
+ self.os.write(fd0, b"aaaa")
+ self.os.write(fd1, b"bb")
self.assertEqual(4, self.os.path.getsize(file_path))
- self.check_contents(file_path, b'bbaa')
+ self.check_contents(file_path, b"bbaa")
self.os.close(fd1)
self.os.close(fd0)
def test_write_from_different_fds_with_append(self):
# Regression test for #268
- file_path = self.make_path('baz')
+ file_path = self.make_path("baz")
fd0 = self.os.open(file_path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
fd1 = self.os.open(file_path, os.O_WRONLY | os.O_APPEND)
- self.os.write(fd0, b'aaa')
- self.os.write(fd1, b'bbb')
+ self.os.write(fd0, b"aaa")
+ self.os.write(fd1, b"bbb")
self.assertEqual(6, self.os.path.getsize(file_path))
- self.check_contents(file_path, b'aaabbb')
+ self.check_contents(file_path, b"aaabbb")
self.os.close(fd1)
self.os.close(fd0)
def test_read_only_read_after_write(self):
# Regression test for #269
self.check_posix_only()
- file_path = self.make_path('foo', 'bar', 'baz')
- self.create_file(file_path, contents=b'test')
+ file_path = self.make_path("foo", "bar", "baz")
+ self.create_file(file_path, contents=b"test")
fd0 = self.os.open(file_path, os.O_CREAT)
fd1 = self.os.open(file_path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
- self.assertEqual(b'', self.os.read(fd0, 0))
+ self.assertEqual(b"", self.os.read(fd0, 0))
self.os.close(fd1)
self.os.close(fd0)
def test_read_after_closing_write_descriptor(self):
# Regression test for #271
- file_path = self.make_path('baz')
+ file_path = self.make_path("baz")
fd0 = self.os.open(file_path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
fd1 = self.os.open(file_path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
fd2 = self.os.open(file_path, os.O_CREAT)
- self.os.write(fd1, b'abc')
+ self.os.write(fd1, b"abc")
self.os.close(fd0)
- self.assertEqual(b'abc', self.os.read(fd2, 3))
+ self.assertEqual(b"abc", self.os.read(fd2, 3))
self.os.close(fd2)
self.os.close(fd1)
def test_writing_behind_end_of_file(self):
# Regression test for #273
- file_path = self.make_path('baz')
+ file_path = self.make_path("baz")
fd1 = self.os.open(file_path, os.O_CREAT)
fd2 = self.os.open(file_path, os.O_RDWR)
- self.os.write(fd2, b'm')
+ self.os.write(fd2, b"m")
fd3 = self.os.open(file_path, os.O_CREAT | os.O_WRONLY | os.O_TRUNC)
- self.assertEqual(b'', self.os.read(fd2, 1))
- self.os.write(fd2, b'm')
- self.assertEqual(b'\x00m', self.os.read(fd1, 2))
+ self.assertEqual(b"", self.os.read(fd2, 1))
+ self.os.write(fd2, b"m")
+ self.assertEqual(b"\x00m", self.os.read(fd1, 2))
self.os.close(fd1)
self.os.close(fd2)
self.os.close(fd3)
def test_devnull_posix(self):
self.check_posix_only()
+ # make sure os.devnull is correctly set after changing the filesystem
+ self.setup_fake_fs()
self.assertTrue(self.os.path.exists(self.os.devnull))
def test_devnull_windows(self):
self.check_windows_only()
+ # make sure os.devnull is correctly set after changing the filesystem
+ self.setup_fake_fs()
if sys.version_info < (3, 8):
self.assertFalse(self.os.path.exists(self.os.devnull))
else:
@@ -4339,31 +4368,29 @@ class FakeOsModuleLowLevelFileOpTest(FakeOsModuleTestBase):
def test_write_devnull(self):
fd = self.os.open(self.os.devnull, os.O_RDWR)
- self.assertEqual(4, self.os.write(fd, b'test'))
- self.assertEqual(b'', self.os.read(fd, 4))
+ self.assertEqual(4, self.os.write(fd, b"test"))
+ self.assertEqual(b"", self.os.read(fd, 4))
self.os.close(fd)
fd = self.os.open(self.os.devnull, os.O_RDONLY)
- self.assertEqual(b'', self.os.read(fd, 4))
+ self.assertEqual(b"", self.os.read(fd, 4))
self.os.close(fd)
def test_sendfile_with_invalid_fd(self):
self.check_linux_only()
- self.assert_raises_os_error(errno.EBADF, self.os.sendfile,
- 100, 101, 0, 100)
- src_file_path = self.make_path('foo')
- dst_file_path = self.make_path('bar')
- self.create_file(src_file_path, 'testcontent')
+ self.assert_raises_os_error(errno.EBADF, self.os.sendfile, 100, 101, 0, 100)
+ src_file_path = self.make_path("foo")
+ dst_file_path = self.make_path("bar")
+ self.create_file(src_file_path, "testcontent")
self.create_file(dst_file_path)
fd1 = self.os.open(src_file_path, os.O_RDONLY)
fd2 = self.os.open(dst_file_path, os.O_RDONLY)
- self.assert_raises_os_error(errno.EBADF, self.os.sendfile,
- fd2, fd1, 0, 4)
+ self.assert_raises_os_error(errno.EBADF, self.os.sendfile, fd2, fd1, 0, 4)
def test_sendfile_no_offset(self):
self.check_linux_only()
- src_file_path = self.make_path('foo')
- dst_file_path = self.make_path('bar')
- self.create_file(src_file_path, 'testcontent')
+ src_file_path = self.make_path("foo")
+ dst_file_path = self.make_path("bar")
+ self.create_file(src_file_path, "testcontent")
self.create_file(dst_file_path)
fd1 = self.os.open(src_file_path, os.O_RDONLY)
fd2 = self.os.open(dst_file_path, os.O_RDWR)
@@ -4371,13 +4398,13 @@ class FakeOsModuleLowLevelFileOpTest(FakeOsModuleTestBase):
self.os.close(fd2)
self.os.close(fd1)
with self.open(dst_file_path) as f:
- self.assertEqual('tes', f.read())
+ self.assertEqual("tes", f.read())
def test_sendfile_with_offset(self):
self.check_linux_only()
- src_file_path = self.make_path('foo')
- dst_file_path = self.make_path('bar')
- self.create_file(src_file_path, 'testcontent')
+ src_file_path = self.make_path("foo")
+ dst_file_path = self.make_path("bar")
+ self.create_file(src_file_path, "testcontent")
self.create_file(dst_file_path)
fd1 = self.os.open(src_file_path, os.O_RDONLY)
fd2 = self.os.open(dst_file_path, os.O_RDWR)
@@ -4385,13 +4412,13 @@ class FakeOsModuleLowLevelFileOpTest(FakeOsModuleTestBase):
self.os.close(fd2)
self.os.close(fd1)
with self.open(dst_file_path) as f:
- self.assertEqual('cont', f.read())
+ self.assertEqual("cont", f.read())
def test_sendfile_twice(self):
self.check_linux_only()
- src_file_path = self.make_path('foo')
- dst_file_path = self.make_path('bar')
- self.create_file(src_file_path, 'testcontent')
+ src_file_path = self.make_path("foo")
+ dst_file_path = self.make_path("bar")
+ self.create_file(src_file_path, "testcontent")
self.create_file(dst_file_path)
fd1 = self.os.open(src_file_path, os.O_RDONLY)
fd2 = self.os.open(dst_file_path, os.O_RDWR)
@@ -4400,13 +4427,13 @@ class FakeOsModuleLowLevelFileOpTest(FakeOsModuleTestBase):
self.os.close(fd2)
self.os.close(fd1)
with self.open(dst_file_path) as f:
- self.assertEqual('contcont', f.read())
+ self.assertEqual("contcont", f.read())
def test_sendfile_offset_none(self):
self.check_linux_only()
- src_file_path = self.make_path('foo')
- dst_file_path = self.make_path('bar')
- self.create_file(src_file_path, 'testcontent')
+ src_file_path = self.make_path("foo")
+ dst_file_path = self.make_path("bar")
+ self.create_file(src_file_path, "testcontent")
self.create_file(dst_file_path)
fd1 = self.os.open(src_file_path, os.O_RDONLY)
fd2 = self.os.open(dst_file_path, os.O_RDWR)
@@ -4415,13 +4442,13 @@ class FakeOsModuleLowLevelFileOpTest(FakeOsModuleTestBase):
self.os.close(fd2)
self.os.close(fd1)
with self.open(dst_file_path) as f:
- self.assertEqual('testcon', f.read())
+ self.assertEqual("testcon", f.read())
- @unittest.skipIf(not TestCase.is_macos, 'Testing MacOs only behavior')
+ @unittest.skipIf(not TestCase.is_macos, "Testing MacOs only behavior")
def test_no_sendfile_to_regular_file_under_macos(self):
- src_file_path = self.make_path('foo')
- dst_file_path = self.make_path('bar')
- self.create_file(src_file_path, 'testcontent')
+ src_file_path = self.make_path("foo")
+ dst_file_path = self.make_path("bar")
+ self.create_file(src_file_path, "testcontent")
self.create_file(dst_file_path)
fd1 = self.os.open(src_file_path, os.O_RDONLY)
fd2 = self.os.open(dst_file_path, os.O_RDWR)
@@ -4437,12 +4464,12 @@ class RealOsModuleLowLevelFileOpTest(FakeOsModuleLowLevelFileOpTest):
class FakeOsModuleWalkTest(FakeOsModuleTestBase):
- def assertWalkResults(self, expected, top, topdown=True,
- followlinks=False):
+ def assertWalkResults(self, expected, top, topdown=True, followlinks=False):
# as the result of walk is unsorted, we have to check against
# sorted results
- result = [step for step in self.os.walk(
- top, topdown=topdown, followlinks=followlinks)]
+ result = list(
+ step for step in self.os.walk(top, topdown=topdown, followlinks=followlinks)
+ )
result = sorted(result, key=lambda lst: lst[0])
expected = sorted(expected, key=lambda lst: lst[0])
self.assertEqual(len(expected), len(result))
@@ -4465,46 +4492,46 @@ class FakeOsModuleWalkTest(FakeOsModuleTestBase):
def test_walk_top_down(self):
"""Walk down ordering is correct."""
- base_dir = self.make_path('foo')
- self.create_file(self.os.path.join(base_dir, '1.txt'))
- self.create_file(self.os.path.join(base_dir, 'bar1', '2.txt'))
- self.create_file(self.os.path.join(base_dir, 'bar1', 'baz', '3.txt'))
- self.create_file(self.os.path.join(base_dir, 'bar2', '4.txt'))
+ base_dir = self.make_path("foo")
+ self.create_file(self.os.path.join(base_dir, "1.txt"))
+ self.create_file(self.os.path.join(base_dir, "bar1", "2.txt"))
+ self.create_file(self.os.path.join(base_dir, "bar1", "baz", "3.txt"))
+ self.create_file(self.os.path.join(base_dir, "bar2", "4.txt"))
expected = [
- (base_dir, ['bar1', 'bar2'], ['1.txt']),
- (self.os.path.join(base_dir, 'bar1'), ['baz'], ['2.txt']),
- (self.os.path.join(base_dir, 'bar1', 'baz'), [], ['3.txt']),
- (self.os.path.join(base_dir, 'bar2'), [], ['4.txt']),
+ (base_dir, ["bar1", "bar2"], ["1.txt"]),
+ (self.os.path.join(base_dir, "bar1"), ["baz"], ["2.txt"]),
+ (self.os.path.join(base_dir, "bar1", "baz"), [], ["3.txt"]),
+ (self.os.path.join(base_dir, "bar2"), [], ["4.txt"]),
]
self.assertWalkResults(expected, base_dir)
def test_walk_bottom_up(self):
"""Walk up ordering is correct."""
- base_dir = self.make_path('foo')
- self.create_file(self.os.path.join(base_dir, 'bar1', 'baz', '1.txt'))
- self.create_file(self.os.path.join(base_dir, 'bar1', '2.txt'))
- self.create_file(self.os.path.join(base_dir, 'bar2', '3.txt'))
- self.create_file(self.os.path.join(base_dir, '4.txt'))
+ base_dir = self.make_path("foo")
+ self.create_file(self.os.path.join(base_dir, "bar1", "baz", "1.txt"))
+ self.create_file(self.os.path.join(base_dir, "bar1", "2.txt"))
+ self.create_file(self.os.path.join(base_dir, "bar2", "3.txt"))
+ self.create_file(self.os.path.join(base_dir, "4.txt"))
expected = [
- (self.os.path.join(base_dir, 'bar1', 'baz'), [], ['1.txt']),
- (self.os.path.join(base_dir, 'bar1'), ['baz'], ['2.txt']),
- (self.os.path.join(base_dir, 'bar2'), [], ['3.txt']),
- (base_dir, ['bar1', 'bar2'], ['4.txt']),
+ (self.os.path.join(base_dir, "bar1", "baz"), [], ["1.txt"]),
+ (self.os.path.join(base_dir, "bar1"), ["baz"], ["2.txt"]),
+ (self.os.path.join(base_dir, "bar2"), [], ["3.txt"]),
+ (base_dir, ["bar1", "bar2"], ["4.txt"]),
]
- self.assertWalkResults(expected, self.make_path('foo'), topdown=False)
+ self.assertWalkResults(expected, self.make_path("foo"), topdown=False)
def test_walk_raises_if_non_existent(self):
"""Raises an exception when attempting to walk
- non-existent directory."""
- directory = self.make_path('foo', 'bar')
+ non-existent directory."""
+ directory = self.make_path("foo", "bar")
self.assertEqual(False, self.os.path.exists(directory))
generator = self.os.walk(directory)
self.assertRaises(StopIteration, next, generator)
def test_walk_raises_if_not_directory(self):
"""Raises an exception when attempting to walk a non-directory."""
- filename = self.make_path('foo', 'bar')
+ filename = self.make_path("foo", "bar")
self.create_file(filename)
generator = self.os.walk(filename)
self.assertRaises(StopIteration, next, generator)
@@ -4513,7 +4540,7 @@ class FakeOsModuleWalkTest(FakeOsModuleTestBase):
"""Calls onerror with correct errno when walking
non-existent directory."""
self.ResetErrno()
- directory = self.make_path('foo', 'bar')
+ directory = self.make_path("foo", "bar")
self.assertEqual(False, self.os.path.exists(directory))
# Calling os.walk on a non-existent directory should trigger
# a call to the onerror method.
@@ -4525,7 +4552,7 @@ class FakeOsModuleWalkTest(FakeOsModuleTestBase):
def test_walk_calls_on_error_if_not_directory(self):
"""Calls onerror with correct errno when walking non-directory."""
self.ResetErrno()
- filename = self.make_path('foo' 'bar')
+ filename = self.make_path("foo" "bar")
self.create_file(filename)
self.assertEqual(True, self.os.path.exists(filename))
# Calling `os.walk` on a file should trigger a call to the
@@ -4537,16 +4564,16 @@ class FakeOsModuleWalkTest(FakeOsModuleTestBase):
def test_walk_skips_removed_directories(self):
"""Caller can modify list of directories to visit while walking."""
- root = self.make_path('foo')
- visit = 'visit'
- no_visit = 'no_visit'
- self.create_file(self.os.path.join(root, 'bar'))
- self.create_file(self.os.path.join(root, visit, '1.txt'))
- self.create_file(self.os.path.join(root, visit, '2.txt'))
- self.create_file(self.os.path.join(root, no_visit, '3.txt'))
- self.create_file(self.os.path.join(root, no_visit, '4.txt'))
-
- generator = self.os.walk(self.make_path('foo'))
+ root = self.make_path("foo")
+ visit = "visit"
+ no_visit = "no_visit"
+ self.create_file(self.os.path.join(root, "bar"))
+ self.create_file(self.os.path.join(root, visit, "1.txt"))
+ self.create_file(self.os.path.join(root, visit, "2.txt"))
+ self.create_file(self.os.path.join(root, no_visit, "3.txt"))
+ self.create_file(self.os.path.join(root, no_visit, "4.txt"))
+
+ generator = self.os.walk(self.make_path("foo"))
root_contents = next(generator)
root_contents[1].remove(no_visit)
@@ -4561,84 +4588,83 @@ class FakeOsModuleWalkTest(FakeOsModuleTestBase):
def test_walk_followsymlink_disabled(self):
self.check_posix_only()
- base_dir = self.make_path('foo')
- link_dir = self.make_path('linked')
- self.create_file(self.os.path.join(link_dir, 'subfile'))
- self.create_file(self.os.path.join(base_dir, 'bar', 'baz'))
- self.create_file(self.os.path.join(base_dir, 'bar', 'xyzzy', 'plugh'))
- self.create_symlink(
- self.os.path.join(base_dir, 'created_link'), link_dir)
+ base_dir = self.make_path("foo")
+ link_dir = self.make_path("linked")
+ self.create_file(self.os.path.join(link_dir, "subfile"))
+ self.create_file(self.os.path.join(base_dir, "bar", "baz"))
+ self.create_file(self.os.path.join(base_dir, "bar", "xyzzy", "plugh"))
+ self.create_symlink(self.os.path.join(base_dir, "created_link"), link_dir)
expected = [
- (base_dir, ['bar', 'created_link'], []),
- (self.os.path.join(base_dir, 'bar'), ['xyzzy'], ['baz']),
- (self.os.path.join(base_dir, 'bar', 'xyzzy'), [], ['plugh']),
+ (base_dir, ["bar", "created_link"], []),
+ (self.os.path.join(base_dir, "bar"), ["xyzzy"], ["baz"]),
+ (self.os.path.join(base_dir, "bar", "xyzzy"), [], ["plugh"]),
]
self.assertWalkResults(expected, base_dir, followlinks=False)
- expected = [(self.os.path.join(base_dir, 'created_link'),
- [], ['subfile'])]
- self.assertWalkResults(expected,
- self.os.path.join(base_dir, 'created_link'),
- followlinks=False)
+ expected = [(self.os.path.join(base_dir, "created_link"), [], ["subfile"])]
+ self.assertWalkResults(
+ expected,
+ self.os.path.join(base_dir, "created_link"),
+ followlinks=False,
+ )
def test_walk_followsymlink_enabled(self):
self.check_posix_only()
- base_dir = self.make_path('foo')
- link_dir = self.make_path('linked')
- self.create_file(self.os.path.join(link_dir, 'subfile'))
- self.create_file(self.os.path.join(base_dir, 'bar', 'baz'))
- self.create_file(self.os.path.join(base_dir, 'bar', 'xyzzy', 'plugh'))
- self.create_symlink(self.os.path.join(base_dir, 'created_link'),
- self.os.path.join(link_dir))
+ base_dir = self.make_path("foo")
+ link_dir = self.make_path("linked")
+ self.create_file(self.os.path.join(link_dir, "subfile"))
+ self.create_file(self.os.path.join(base_dir, "bar", "baz"))
+ self.create_file(self.os.path.join(base_dir, "bar", "xyzzy", "plugh"))
+ self.create_symlink(
+ self.os.path.join(base_dir, "created_link"),
+ self.os.path.join(link_dir),
+ )
expected = [
- (base_dir, ['bar', 'created_link'], []),
- (self.os.path.join(base_dir, 'bar'), ['xyzzy'], ['baz']),
- (self.os.path.join(base_dir, 'bar', 'xyzzy'), [], ['plugh']),
- (self.os.path.join(base_dir, 'created_link'), [], ['subfile']),
+ (base_dir, ["bar", "created_link"], []),
+ (self.os.path.join(base_dir, "bar"), ["xyzzy"], ["baz"]),
+ (self.os.path.join(base_dir, "bar", "xyzzy"), [], ["plugh"]),
+ (self.os.path.join(base_dir, "created_link"), [], ["subfile"]),
]
self.assertWalkResults(expected, base_dir, followlinks=True)
- expected = [(self.os.path.join(base_dir, 'created_link'),
- [], ['subfile'])]
- self.assertWalkResults(expected,
- self.os.path.join(base_dir, 'created_link'),
- followlinks=True)
+ expected = [(self.os.path.join(base_dir, "created_link"), [], ["subfile"])]
+ self.assertWalkResults(
+ expected,
+ self.os.path.join(base_dir, "created_link"),
+ followlinks=True,
+ )
def test_walk_linked_file_in_subdir(self):
# regression test for #559 (tested for link on incomplete path)
self.check_posix_only()
# need to have a top-level link to reproduce the bug - skip real fs
self.skip_real_fs()
- file_path = '/foo/bar/baz'
+ file_path = "/foo/bar/baz"
self.create_file(file_path)
- self.create_symlink('bar', file_path)
- expected = [
- ('/foo', ['bar'], []),
- ('/foo/bar', [], ['baz'])
- ]
- self.assertWalkResults(expected, '/foo')
+ self.create_symlink("bar", file_path)
+ expected = [("/foo", ["bar"], []), ("/foo/bar", [], ["baz"])]
+ self.assertWalkResults(expected, "/foo")
def test_base_dirpath(self):
# regression test for #512
- file_path = self.make_path('foo', 'bar', 'baz')
+ file_path = self.make_path("foo", "bar", "baz")
self.create_file(file_path)
variants = [
- self.make_path('foo', 'bar'),
- self.make_path('foo', '..', 'foo', 'bar'),
- self.make_path('foo', '..', 'foo', 'bar') +
- self.os.path.sep * 3,
- self.make_path('foo') + self.os.path.sep * 3 + 'bar'
+ self.make_path("foo", "bar"),
+ self.make_path("foo", "..", "foo", "bar"),
+ self.make_path("foo", "..", "foo", "bar") + self.os.path.sep * 3,
+ self.make_path("foo") + self.os.path.sep * 3 + "bar",
]
for base_dir in variants:
- for dirpath, dirnames, filenames in self.os.walk(base_dir):
+ for dirpath, _dirnames, _filenames in self.os.walk(base_dir):
self.assertEqual(dirpath, base_dir)
- file_path = self.make_path('foo', 'bar', 'dir', 'baz')
+ file_path = self.make_path("foo", "bar", "dir", "baz")
self.create_file(file_path)
for base_dir in variants:
- for dirpath, dirnames, filenames in self.os.walk(base_dir):
+ for dirpath, _dirnames, _filenames in self.os.walk(base_dir):
self.assertTrue(dirpath.startswith(base_dir))
@@ -4650,289 +4676,338 @@ class RealOsModuleWalkTest(FakeOsModuleWalkTest):
class FakeOsModuleDirFdTest(FakeOsModuleTestBase):
def setUp(self):
super(FakeOsModuleDirFdTest, self).setUp()
- self.os.supports_dir_fd = set()
+ self.os.supports_dir_fd.clear()
self.filesystem.is_windows_fs = False
- self.filesystem.create_dir('/foo/bar')
- self.dir_fd = self.os.open('/foo', os.O_RDONLY)
- self.filesystem.create_file('/foo/baz')
+ self.filesystem.create_dir("/foo/bar")
+ self.dir_fd = self.os.open("/foo", os.O_RDONLY)
+ self.filesystem.create_file("/foo/baz")
def test_access(self):
self.assertRaises(
- NotImplementedError, self.os.access, 'baz', self.os.F_OK,
- dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.access)
- self.assertTrue(
- self.os.access('baz', self.os.F_OK, dir_fd=self.dir_fd))
+ NotImplementedError,
+ self.os.access,
+ "baz",
+ self.os.F_OK,
+ dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.access)
+ self.assertTrue(self.os.access("baz", self.os.F_OK, dir_fd=self.dir_fd))
def test_chmod(self):
self.assertRaises(
- NotImplementedError, self.os.chmod, 'baz', 0o6543,
- dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.chmod)
- self.os.chmod('baz', 0o6543, dir_fd=self.dir_fd)
- st = self.os.stat('/foo/baz')
+ NotImplementedError,
+ self.os.chmod,
+ "baz",
+ 0o6543,
+ dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.chmod)
+ self.os.chmod("baz", 0o6543, dir_fd=self.dir_fd)
+ st = self.os.stat("/foo/baz")
self.assert_mode_equal(0o6543, st.st_mode)
- @unittest.skipIf(not hasattr(os, 'chown'),
- 'chown not on all platforms available')
+ @unittest.skipIf(not hasattr(os, "chown"), "chown not on all platforms available")
def test_chown(self):
self.assertRaises(
- NotImplementedError, self.os.chown, 'baz', 100, 101,
- dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.chown)
- self.os.chown('baz', 100, 101, dir_fd=self.dir_fd)
- st = self.os.stat('/foo/baz')
+ NotImplementedError,
+ self.os.chown,
+ "baz",
+ 100,
+ 101,
+ dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.chown)
+ self.os.chown("baz", 100, 101, dir_fd=self.dir_fd)
+ st = self.os.stat("/foo/baz")
self.assertEqual(st[stat.ST_UID], 100)
self.assertEqual(st[stat.ST_GID], 101)
def test_link_src_fd(self):
self.assertRaises(
- NotImplementedError, self.os.link, 'baz', '/bat',
- src_dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.link)
- self.os.link('baz', '/bat', src_dir_fd=self.dir_fd)
- self.assertTrue(self.os.path.exists('/bat'))
+ NotImplementedError,
+ self.os.link,
+ "baz",
+ "/bat",
+ src_dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.link)
+ self.os.link("baz", "/bat", src_dir_fd=self.dir_fd)
+ self.assertTrue(self.os.path.exists("/bat"))
def test_link_dst_fd(self):
self.assertRaises(
- NotImplementedError, self.os.link, 'baz', '/bat',
- dst_dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.link)
- self.os.link('/foo/baz', 'bat', dst_dir_fd=self.dir_fd)
- self.assertTrue(self.os.path.exists('/foo/bat'))
+ NotImplementedError,
+ self.os.link,
+ "baz",
+ "/bat",
+ dst_dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.link)
+ self.os.link("/foo/baz", "bat", dst_dir_fd=self.dir_fd)
+ self.assertTrue(self.os.path.exists("/foo/bat"))
def test_symlink(self):
self.assertRaises(
- NotImplementedError, self.os.symlink, 'baz', '/bat',
- dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.symlink)
- self.os.symlink('baz', '/bat', dir_fd=self.dir_fd)
- self.assertTrue(self.os.path.exists('/bat'))
+ NotImplementedError,
+ self.os.symlink,
+ "baz",
+ "/bat",
+ dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.symlink)
+ self.os.symlink("baz", "/bat", dir_fd=self.dir_fd)
+ self.assertTrue(self.os.path.exists("/bat"))
def test_readlink(self):
self.skip_if_symlink_not_supported()
- self.filesystem.create_symlink('/meyer/lemon/pie', '/foo/baz')
- self.filesystem.create_symlink('/geo/metro', '/meyer')
+ self.filesystem.create_symlink("/meyer/lemon/pie", "/foo/baz")
+ self.filesystem.create_symlink("/geo/metro", "/meyer")
self.assertRaises(
- NotImplementedError, self.os.readlink, '/geo/metro/lemon/pie',
- dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.readlink)
- self.assertEqual('/foo/baz', self.os.readlink(
- '/geo/metro/lemon/pie', dir_fd=self.dir_fd))
+ NotImplementedError,
+ self.os.readlink,
+ "/geo/metro/lemon/pie",
+ dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.readlink)
+ self.assertEqual(
+ "/foo/baz",
+ self.os.readlink("/geo/metro/lemon/pie", dir_fd=self.dir_fd),
+ )
def test_stat(self):
- self.assertRaises(
- NotImplementedError, self.os.stat, 'baz', dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.stat)
- st = self.os.stat('baz', dir_fd=self.dir_fd)
+ self.assertRaises(NotImplementedError, self.os.stat, "baz", dir_fd=self.dir_fd)
+ self.os.supports_dir_fd.add(self.os.stat)
+ st = self.os.stat("baz", dir_fd=self.dir_fd)
self.assertEqual(st.st_mode, 0o100666)
def test_lstat(self):
- self.assertRaises(
- NotImplementedError, self.os.lstat, 'baz', dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.lstat)
- st = self.os.lstat('baz', dir_fd=self.dir_fd)
+ self.assertRaises(NotImplementedError, self.os.lstat, "baz", dir_fd=self.dir_fd)
+ self.os.supports_dir_fd.add(self.os.lstat)
+ st = self.os.lstat("baz", dir_fd=self.dir_fd)
self.assertEqual(st.st_mode, 0o100666)
def test_mkdir(self):
self.assertRaises(
- NotImplementedError, self.os.mkdir, 'newdir', dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.mkdir)
- self.os.mkdir('newdir', dir_fd=self.dir_fd)
- self.assertTrue(self.os.path.exists('/foo/newdir'))
+ NotImplementedError, self.os.mkdir, "newdir", dir_fd=self.dir_fd
+ )
+ self.os.supports_dir_fd.add(self.os.mkdir)
+ self.os.mkdir("newdir", dir_fd=self.dir_fd)
+ self.assertTrue(self.os.path.exists("/foo/newdir"))
def test_rmdir(self):
- self.assertRaises(
- NotImplementedError, self.os.rmdir, 'bar', dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.rmdir)
- self.os.rmdir('bar', dir_fd=self.dir_fd)
- self.assertFalse(self.os.path.exists('/foo/bar'))
+ self.assertRaises(NotImplementedError, self.os.rmdir, "bar", dir_fd=self.dir_fd)
+ self.os.supports_dir_fd.add(self.os.rmdir)
+ self.os.rmdir("bar", dir_fd=self.dir_fd)
+ self.assertFalse(self.os.path.exists("/foo/bar"))
- @unittest.skipIf(not hasattr(os, 'mknod'),
- 'mknod not on all platforms available')
+ @unittest.skipIf(not hasattr(os, "mknod"), "mknod not on all platforms available")
def test_mknod(self):
self.assertRaises(
- NotImplementedError, self.os.mknod, 'newdir', dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.mknod)
- self.os.mknod('newdir', dir_fd=self.dir_fd)
- self.assertTrue(self.os.path.exists('/foo/newdir'))
+ NotImplementedError, self.os.mknod, "newdir", dir_fd=self.dir_fd
+ )
+ self.os.supports_dir_fd.add(self.os.mknod)
+ self.os.mknod("newdir", dir_fd=self.dir_fd)
+ self.assertTrue(self.os.path.exists("/foo/newdir"))
def test_rename_src_fd(self):
self.assertRaises(
- NotImplementedError, self.os.rename, 'baz', '/foo/batz',
- src_dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.rename)
- self.os.rename('bar', '/foo/batz', src_dir_fd=self.dir_fd)
- self.assertTrue(self.os.path.exists('/foo/batz'))
+ NotImplementedError,
+ self.os.rename,
+ "baz",
+ "/foo/batz",
+ src_dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.rename)
+ self.os.rename("bar", "/foo/batz", src_dir_fd=self.dir_fd)
+ self.assertTrue(self.os.path.exists("/foo/batz"))
def test_rename_dst_fd(self):
self.assertRaises(
- NotImplementedError, self.os.rename, 'baz', '/foo/batz',
- dst_dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.rename)
- self.os.rename('/foo/bar', 'batz', dst_dir_fd=self.dir_fd)
- self.assertTrue(self.os.path.exists('/foo/batz'))
+ NotImplementedError,
+ self.os.rename,
+ "baz",
+ "/foo/batz",
+ dst_dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.rename)
+ self.os.rename("/foo/bar", "batz", dst_dir_fd=self.dir_fd)
+ self.assertTrue(self.os.path.exists("/foo/batz"))
def test_replace_src_fd(self):
self.assertRaises(
- NotImplementedError, self.os.rename, 'baz', '/foo/batz',
- src_dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.rename)
- self.os.replace('bar', '/foo/batz', src_dir_fd=self.dir_fd)
- self.assertTrue(self.os.path.exists('/foo/batz'))
+ NotImplementedError,
+ self.os.rename,
+ "baz",
+ "/foo/batz",
+ src_dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.rename)
+ self.os.replace("bar", "/foo/batz", src_dir_fd=self.dir_fd)
+ self.assertTrue(self.os.path.exists("/foo/batz"))
def test_replace_dst_fd(self):
self.assertRaises(
- NotImplementedError, self.os.rename, 'baz', '/foo/batz',
- dst_dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.rename)
- self.os.replace('/foo/bar', 'batz', dst_dir_fd=self.dir_fd)
- self.assertTrue(self.os.path.exists('/foo/batz'))
+ NotImplementedError,
+ self.os.rename,
+ "baz",
+ "/foo/batz",
+ dst_dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.rename)
+ self.os.replace("/foo/bar", "batz", dst_dir_fd=self.dir_fd)
+ self.assertTrue(self.os.path.exists("/foo/batz"))
def test_remove(self):
self.assertRaises(
- NotImplementedError, self.os.remove, 'baz', dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.remove)
- self.os.remove('baz', dir_fd=self.dir_fd)
- self.assertFalse(self.os.path.exists('/foo/baz'))
+ NotImplementedError, self.os.remove, "baz", dir_fd=self.dir_fd
+ )
+ self.os.supports_dir_fd.add(self.os.remove)
+ self.os.remove("baz", dir_fd=self.dir_fd)
+ self.assertFalse(self.os.path.exists("/foo/baz"))
def test_unlink(self):
self.assertRaises(
- NotImplementedError, self.os.unlink, 'baz', dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.unlink)
- self.os.unlink('baz', dir_fd=self.dir_fd)
- self.assertFalse(self.os.path.exists('/foo/baz'))
+ NotImplementedError, self.os.unlink, "baz", dir_fd=self.dir_fd
+ )
+ self.os.supports_dir_fd.add(self.os.unlink)
+ self.os.unlink("baz", dir_fd=self.dir_fd)
+ self.assertFalse(self.os.path.exists("/foo/baz"))
def test_utime(self):
self.assertRaises(
- NotImplementedError, self.os.utime, 'baz', (1, 2),
- dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.utime)
- self.os.utime('baz', times=(1, 2), dir_fd=self.dir_fd)
- st = self.os.stat('/foo/baz')
+ NotImplementedError,
+ self.os.utime,
+ "baz",
+ (1, 2),
+ dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.utime)
+ self.os.utime("baz", times=(1, 2), dir_fd=self.dir_fd)
+ st = self.os.stat("/foo/baz")
self.assertEqual(1, st.st_atime)
self.assertEqual(2, st.st_mtime)
def test_open(self):
self.assertRaises(
- NotImplementedError, self.os.open, 'baz', os.O_RDONLY,
- dir_fd=self.dir_fd)
- self.os.supports_dir_fd.add(os.open)
- fd = self.os.open('baz', os.O_RDONLY, dir_fd=self.dir_fd)
+ NotImplementedError,
+ self.os.open,
+ "baz",
+ os.O_RDONLY,
+ dir_fd=self.dir_fd,
+ )
+ self.os.supports_dir_fd.add(self.os.open)
+ fd = self.os.open("baz", os.O_RDONLY, dir_fd=self.dir_fd)
self.assertLess(0, fd)
class StatPropagationTest(TestCase):
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(path_separator='/')
- self.os = fake_filesystem.FakeOsModule(self.filesystem)
- self.open = fake_filesystem.FakeFileOpen(self.filesystem)
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
+ self.os = fake_os.FakeOsModule(self.filesystem)
+ self.open = fake_open.FakeFileOpen(self.filesystem)
def test_file_size_updated_via_close(self):
"""test that file size gets updated via close()."""
- file_dir = 'xyzzy'
- file_path = 'xyzzy/close'
- content = 'This is a test.'
+ file_dir = "xyzzy"
+ file_path = "xyzzy/close"
+ content = "This is a test."
self.os.mkdir(file_dir)
- fh = self.open(file_path, 'w')
+ fh = self.open(file_path, "w")
self.assertEqual(0, self.os.stat(file_path)[stat.ST_SIZE])
- self.assertEqual('', self.filesystem.get_object(file_path).contents)
+ self.assertEqual("", self.filesystem.get_object(file_path).contents)
fh.write(content)
self.assertEqual(0, self.os.stat(file_path)[stat.ST_SIZE])
- self.assertEqual('', self.filesystem.get_object(file_path).contents)
+ self.assertEqual("", self.filesystem.get_object(file_path).contents)
fh.close()
self.assertEqual(len(content), self.os.stat(file_path)[stat.ST_SIZE])
- self.assertEqual(content,
- self.filesystem.get_object(file_path).contents)
+ self.assertEqual(content, self.filesystem.get_object(file_path).contents)
def test_file_size_not_reset_after_close(self):
- file_dir = 'xyzzy'
- file_path = 'xyzzy/close'
+ file_dir = "xyzzy"
+ file_path = "xyzzy/close"
self.os.mkdir(file_dir)
size = 1234
# The file has size, but no content. When the file is opened for
# reading, its size should be preserved.
self.filesystem.create_file(file_path, st_size=size)
- fh = self.open(file_path, 'r')
+ fh = self.open(file_path, "r")
fh.close()
- self.assertEqual(size, self.open(file_path, 'r').size())
+ self.assertEqual(size, self.open(file_path, "r").size())
def test_file_size_after_write(self):
- file_path = 'test_file'
- original_content = 'abcdef'
+ file_path = "test_file"
+ original_content = "abcdef"
original_size = len(original_content)
self.filesystem.create_file(file_path, contents=original_content)
- added_content = 'foo bar'
+ added_content = "foo bar"
expected_size = original_size + len(added_content)
- fh = self.open(file_path, 'a')
+ fh = self.open(file_path, "a")
fh.write(added_content)
self.assertEqual(original_size, fh.size())
fh.close()
- self.assertEqual(expected_size, self.open(file_path, 'r').size())
+ self.assertEqual(expected_size, self.open(file_path, "r").size())
def test_large_file_size_after_write(self):
- file_path = 'test_file'
- original_content = 'abcdef'
+ file_path = "test_file"
+ original_content = "abcdef"
original_size = len(original_content)
self.filesystem.create_file(file_path, st_size=original_size)
- added_content = 'foo bar'
- fh = self.open(file_path, 'a')
- self.assertRaises(fake_filesystem.FakeLargeFileIoException,
- lambda: fh.write(added_content))
+ added_content = "foo bar"
+ fh = self.open(file_path, "a")
+ self.assertRaises(
+ fake_file.FakeLargeFileIoException,
+ lambda: fh.write(added_content),
+ )
def test_file_size_updated_via_flush(self):
"""test that file size gets updated via flush()."""
- file_dir = 'xyzzy'
- file_name = 'flush'
+ file_dir = "xyzzy"
+ file_name = "flush"
file_path = self.os.path.join(file_dir, file_name)
- content = 'This might be a test.'
+ content = "This might be a test."
self.os.mkdir(file_dir)
- fh = self.open(file_path, 'w')
+ fh = self.open(file_path, "w")
self.assertEqual(0, self.os.stat(file_path)[stat.ST_SIZE])
- self.assertEqual('', self.filesystem.get_object(file_path).contents)
+ self.assertEqual("", self.filesystem.get_object(file_path).contents)
fh.write(content)
self.assertEqual(0, self.os.stat(file_path)[stat.ST_SIZE])
- self.assertEqual('', self.filesystem.get_object(file_path).contents)
+ self.assertEqual("", self.filesystem.get_object(file_path).contents)
fh.flush()
self.assertEqual(len(content), self.os.stat(file_path)[stat.ST_SIZE])
- self.assertEqual(content,
- self.filesystem.get_object(file_path).contents)
+ self.assertEqual(content, self.filesystem.get_object(file_path).contents)
fh.close()
self.assertEqual(len(content), self.os.stat(file_path)[stat.ST_SIZE])
- self.assertEqual(content,
- self.filesystem.get_object(file_path).contents)
+ self.assertEqual(content, self.filesystem.get_object(file_path).contents)
def test_file_size_truncation(self):
"""test that file size gets updated via open()."""
- file_dir = 'xyzzy'
- file_path = 'xyzzy/truncation'
- content = 'AAA content.'
+ file_dir = "xyzzy"
+ file_path = "xyzzy/truncation"
+ content = "AAA content."
# pre-create file with content
self.os.mkdir(file_dir)
- fh = self.open(file_path, 'w')
+ fh = self.open(file_path, "w")
fh.write(content)
fh.close()
self.assertEqual(len(content), self.os.stat(file_path)[stat.ST_SIZE])
- self.assertEqual(content,
- self.filesystem.get_object(file_path).contents)
+ self.assertEqual(content, self.filesystem.get_object(file_path).contents)
# test file truncation
- fh = self.open(file_path, 'w')
+ fh = self.open(file_path, "w")
self.assertEqual(0, self.os.stat(file_path)[stat.ST_SIZE])
- self.assertEqual('', self.filesystem.get_object(file_path).contents)
+ self.assertEqual("", self.filesystem.get_object(file_path).contents)
fh.close()
-@unittest.skipIf(not use_scandir, 'only run if scandir is available')
+@unittest.skipIf(not use_scandir, "only run if scandir is available")
class FakeScandirTest(FakeOsModuleTestBase):
FILE_SIZE = 50
LINKED_FILE_SIZE = 10
def setUp(self):
super(FakeScandirTest, self).setUp()
- self.supports_symlinks = (not self.is_windows or
- not self.use_real_fs())
+ self.supports_symlinks = not self.is_windows or not self.use_real_fs()
if use_scandir_package:
if self.use_real_fs():
@@ -4948,35 +5023,34 @@ class FakeScandirTest(FakeOsModuleTestBase):
scandir = self.os.scandir
self.scandir = scandir
- self.directory = self.make_path('xyzzy', 'plugh')
- link_dir = self.make_path('linked', 'plugh')
- self.linked_file_path = self.os.path.join(link_dir, 'file')
- self.linked_dir_path = self.os.path.join(link_dir, 'dir')
- self.rel_linked_dir_path = (
- self.os.path.join('..', '..', 'linked', 'plugh', 'dir'))
- self.rel_linked_file_path = (
- self.os.path.join('..', '..', 'linked', 'plugh', 'file'))
- self.dir_path = self.os.path.join(self.directory, 'dir')
- self.file_path = self.os.path.join(self.directory, 'file')
- self.file_link_path = self.os.path.join(self.directory, 'link_file')
- self.dir_link_path = self.os.path.join(self.directory, 'link_dir')
- self.file_rel_link_path = self.os.path.join(self.directory,
- 'rel_link_file')
- self.dir_rel_link_path = self.os.path.join(self.directory,
- 'rel_link_dir')
+ self.directory = self.make_path("xyzzy", "plugh")
+ link_dir = self.make_path("linked", "plugh")
+ self.linked_file_path = self.os.path.join(link_dir, "file")
+ self.linked_dir_path = self.os.path.join(link_dir, "dir")
+ self.rel_linked_dir_path = self.os.path.join(
+ "..", "..", "linked", "plugh", "dir"
+ )
+ self.rel_linked_file_path = self.os.path.join(
+ "..", "..", "linked", "plugh", "file"
+ )
+ self.dir_path = self.os.path.join(self.directory, "dir")
+ self.file_path = self.os.path.join(self.directory, "file")
+ self.file_link_path = self.os.path.join(self.directory, "link_file")
+ self.dir_link_path = self.os.path.join(self.directory, "link_dir")
+ self.file_rel_link_path = self.os.path.join(self.directory, "rel_link_file")
+ self.dir_rel_link_path = self.os.path.join(self.directory, "rel_link_dir")
self.create_dir(self.dir_path)
- self.create_file(self.file_path, contents=b'b' * self.FILE_SIZE)
+ self.create_file(self.file_path, contents=b"b" * self.FILE_SIZE)
if self.supports_symlinks:
self.create_dir(self.linked_dir_path)
- self.create_file(self.linked_file_path,
- contents=b'a' * self.LINKED_FILE_SIZE),
+ self.create_file(
+ self.linked_file_path, contents=b"a" * self.LINKED_FILE_SIZE
+ ),
self.create_symlink(self.dir_link_path, self.linked_dir_path)
self.create_symlink(self.file_link_path, self.linked_file_path)
- self.create_symlink(self.dir_rel_link_path,
- self.rel_linked_dir_path)
- self.create_symlink(self.file_rel_link_path,
- self.rel_linked_file_path)
+ self.create_symlink(self.dir_rel_link_path, self.rel_linked_dir_path)
+ self.create_symlink(self.file_rel_link_path, self.rel_linked_file_path)
# Changing the working directory below is to make sure relative paths
# to the files and directories created above are reasonable.
@@ -5004,35 +5078,31 @@ class FakeScandirTest(FakeOsModuleTestBase):
return self.directory
def test_paths(self):
- sorted_names = ['dir', 'file']
+ sorted_names = ["dir", "file"]
if self.supports_symlinks:
- sorted_names.extend(['link_dir', 'link_file', 'rel_link_dir',
- 'rel_link_file'])
+ sorted_names.extend(
+ ["link_dir", "link_file", "rel_link_dir", "rel_link_file"]
+ )
self.assertEqual(len(sorted_names), len(self.dir_entries))
- self.assertEqual(sorted_names,
- [entry.name for entry in self.dir_entries])
- sorted_paths = [self.os.path.join(self.scandir_path(), name)
- for name in sorted_names]
- self.assertEqual(sorted_paths,
- [entry.path for entry in self.dir_entries])
+ self.assertEqual(sorted_names, [entry.name for entry in self.dir_entries])
+ sorted_paths = [
+ self.os.path.join(self.scandir_path(), name) for name in sorted_names
+ ]
+ self.assertEqual(sorted_paths, [entry.path for entry in self.dir_entries])
def test_isfile(self):
self.assertFalse(self.dir_entries[0].is_file())
self.assertTrue(self.dir_entries[1].is_file())
if self.supports_symlinks:
self.assertFalse(self.dir_entries[2].is_file())
- self.assertFalse(
- self.dir_entries[2].is_file(follow_symlinks=False))
+ self.assertFalse(self.dir_entries[2].is_file(follow_symlinks=False))
self.assertTrue(self.dir_entries[3].is_file())
- self.assertFalse(
- self.dir_entries[3].is_file(follow_symlinks=False))
+ self.assertFalse(self.dir_entries[3].is_file(follow_symlinks=False))
self.assertFalse(self.dir_entries[4].is_file())
- self.assertFalse(
- self.dir_entries[4].is_file(follow_symlinks=False))
+ self.assertFalse(self.dir_entries[4].is_file(follow_symlinks=False))
self.assertTrue(self.dir_entries[5].is_file())
- self.assertFalse(
- self.dir_entries[5].is_file(follow_symlinks=False))
+ self.assertFalse(self.dir_entries[5].is_file(follow_symlinks=False))
def test_isdir(self):
self.assertTrue(self.dir_entries[0].is_dir())
@@ -5059,34 +5129,44 @@ class FakeScandirTest(FakeOsModuleTestBase):
def test_path_links_not_resolved(self):
# regression test for #350
self.skip_if_symlink_not_supported()
- dir_path = self.make_path('A', 'B', 'C')
- self.os.makedirs(self.os.path.join(dir_path, 'D'))
- link_path = self.make_path('A', 'C')
+ dir_path = self.make_path("A", "B", "C")
+ self.os.makedirs(self.os.path.join(dir_path, "D"))
+ link_path = self.make_path("A", "C")
self.os.symlink(dir_path, link_path)
- self.assertEqual([self.os.path.join(link_path, 'D')],
- [f.path for f in self.scandir(link_path)])
+ self.assertEqual(
+ [self.os.path.join(link_path, "D")],
+ [f.path for f in self.scandir(link_path)],
+ )
def test_inode(self):
if use_scandir and self.use_real_fs():
if self.is_windows:
- self.skipTest(
- 'inode seems not to work in scandir module under Windows')
+ self.skipTest("inode seems not to work in scandir module under Windows")
if IN_DOCKER:
- self.skipTest(
- 'inode seems not to work in a Docker container')
- self.assertEqual(self.os.stat(self.dir_path).st_ino,
- self.dir_entries[0].inode())
- self.assertEqual(self.os.stat(self.file_path).st_ino,
- self.dir_entries[1].inode())
+ self.skipTest("inode seems not to work in a Docker container")
+ self.assertEqual(
+ self.os.stat(self.dir_path).st_ino, self.dir_entries[0].inode()
+ )
+ self.assertEqual(
+ self.os.stat(self.file_path).st_ino, self.dir_entries[1].inode()
+ )
if self.supports_symlinks:
- self.assertEqual(self.os.lstat(self.dir_link_path).st_ino,
- self.dir_entries[2].inode())
- self.assertEqual(self.os.lstat(self.file_link_path).st_ino,
- self.dir_entries[3].inode())
- self.assertEqual(self.os.lstat(self.dir_rel_link_path).st_ino,
- self.dir_entries[4].inode())
- self.assertEqual(self.os.lstat(self.file_rel_link_path).st_ino,
- self.dir_entries[5].inode())
+ self.assertEqual(
+ self.os.lstat(self.dir_link_path).st_ino,
+ self.dir_entries[2].inode(),
+ )
+ self.assertEqual(
+ self.os.lstat(self.file_link_path).st_ino,
+ self.dir_entries[3].inode(),
+ )
+ self.assertEqual(
+ self.os.lstat(self.dir_rel_link_path).st_ino,
+ self.dir_entries[4].inode(),
+ )
+ self.assertEqual(
+ self.os.lstat(self.file_rel_link_path).st_ino,
+ self.dir_entries[5].inode(),
+ )
def test_scandir_stat_nlink(self):
# regression test for #350
@@ -5102,75 +5182,103 @@ class FakeScandirTest(FakeOsModuleTestBase):
self.assertEqual(1, scandir_stat_nlink)
self.assertEqual(1, self.os.stat(self.file_path).st_nlink)
- def check_stat(self, absolute_symlink_expected_size,
- relative_symlink_expected_size):
+ @unittest.skipIf(not hasattr(os, "O_DIRECTORY"), "opening directory not supported")
+ @unittest.skipIf(sys.version_info < (3, 7), "fd not supported for scandir")
+ def test_scandir_with_fd(self):
+ # regression test for #723
+ temp_dir = self.make_path("tmp", "dir")
+ self.create_dir(temp_dir)
+ self.create_file(self.os.path.join(temp_dir, "file1"))
+ self.create_file(self.os.path.join(temp_dir, "file2"))
+ self.create_dir(self.os.path.join(temp_dir, "subdir"))
+ self.os.chdir(temp_dir)
+ fd = self.os.open(temp_dir, flags=os.O_RDONLY | os.O_DIRECTORY)
+ children = [dir_entry.name for dir_entry in self.os.scandir(fd)]
+ assert sorted(children) == ["file1", "file2", "subdir"]
+
+ def check_stat(
+ self, absolute_symlink_expected_size, relative_symlink_expected_size
+ ):
self.assertEqual(self.FILE_SIZE, self.dir_entries[1].stat().st_size)
- self.assertEqual(
- int(self.os.stat(self.dir_path).st_ctime),
- int(self.dir_entries[0].stat().st_ctime))
+ if not self.is_windows_fs or sys.version_info < (3, 12):
+ # behavior of st_ctime changed in 3.12, to be adapted later
+ self.assertEqual(
+ int(self.os.stat(self.dir_path).st_ctime),
+ int(self.dir_entries[0].stat().st_ctime),
+ )
if self.supports_symlinks:
- self.assertEqual(self.LINKED_FILE_SIZE,
- self.dir_entries[3].stat().st_size)
- self.assertEqual(absolute_symlink_expected_size,
- self.dir_entries[3].stat(
- follow_symlinks=False).st_size)
+ self.assertEqual(self.LINKED_FILE_SIZE, self.dir_entries[3].stat().st_size)
+ self.assertEqual(
+ absolute_symlink_expected_size,
+ self.dir_entries[3].stat(follow_symlinks=False).st_size,
+ )
self.assertEqual(
int(self.os.stat(self.linked_dir_path).st_mtime),
- int(self.dir_entries[2].stat().st_mtime))
- self.assertEqual(self.LINKED_FILE_SIZE,
- self.dir_entries[5].stat().st_size)
- self.assertEqual(relative_symlink_expected_size,
- self.dir_entries[5].stat(
- follow_symlinks=False).st_size)
+ int(self.dir_entries[2].stat().st_mtime),
+ )
+ self.assertEqual(self.LINKED_FILE_SIZE, self.dir_entries[5].stat().st_size)
+ self.assertEqual(
+ relative_symlink_expected_size,
+ self.dir_entries[5].stat(follow_symlinks=False).st_size,
+ )
self.assertEqual(
int(self.os.stat(self.linked_dir_path).st_mtime),
- int(self.dir_entries[4].stat().st_mtime))
+ int(self.dir_entries[4].stat().st_mtime),
+ )
- @unittest.skipIf(TestCase.is_windows, 'POSIX specific behavior')
+ @unittest.skipIf(TestCase.is_windows, "POSIX specific behavior")
def test_stat_posix(self):
- self.check_stat(len(self.linked_file_path),
- len(self.rel_linked_file_path))
+ self.check_stat(len(self.linked_file_path), len(self.rel_linked_file_path))
- @unittest.skipIf(not TestCase.is_windows, 'Windows specific behavior')
+ @unittest.skipIf(not TestCase.is_windows, "Windows specific behavior")
def test_stat_windows(self):
self.check_stat(0, 0)
def test_index_access_to_stat_times_returns_int(self):
- self.assertEqual(self.os.stat(self.dir_path)[stat.ST_CTIME],
- int(self.dir_entries[0].stat().st_ctime))
+ if not self.is_windows_fs or sys.version_info < (3, 12):
+ # behavior of st_ctime changed in 3.12, to be adapted later
+ self.assertEqual(
+ self.os.stat(self.dir_path)[stat.ST_CTIME],
+ int(self.dir_entries[0].stat().st_ctime),
+ )
if self.supports_symlinks:
- self.assertEqual(self.os.stat(self.linked_dir_path)[stat.ST_MTIME],
- int(self.dir_entries[2].stat().st_mtime))
- self.assertEqual(self.os.stat(self.linked_dir_path)[stat.ST_MTIME],
- int(self.dir_entries[4].stat().st_mtime))
+ self.assertEqual(
+ self.os.stat(self.linked_dir_path)[stat.ST_MTIME],
+ int(self.dir_entries[2].stat().st_mtime),
+ )
+ self.assertEqual(
+ self.os.stat(self.linked_dir_path)[stat.ST_MTIME],
+ int(self.dir_entries[4].stat().st_mtime),
+ )
def test_stat_ino_dev(self):
if self.supports_symlinks:
file_stat = self.os.stat(self.linked_file_path)
- self.assertEqual(file_stat.st_ino,
- self.dir_entries[3].stat().st_ino)
- self.assertEqual(file_stat.st_dev,
- self.dir_entries[3].stat().st_dev)
- self.assertEqual(file_stat.st_ino,
- self.dir_entries[5].stat().st_ino)
- self.assertEqual(file_stat.st_dev,
- self.dir_entries[5].stat().st_dev)
-
- @unittest.skipIf(sys.version_info < (3, 6) or not use_builtin_scandir,
- 'Path-like objects have been introduced in Python 3.6')
+ self.assertEqual(file_stat.st_ino, self.dir_entries[3].stat().st_ino)
+ self.assertEqual(file_stat.st_dev, self.dir_entries[3].stat().st_dev)
+ self.assertEqual(file_stat.st_ino, self.dir_entries[5].stat().st_ino)
+ self.assertEqual(file_stat.st_dev, self.dir_entries[5].stat().st_dev)
+
+ @unittest.skipIf(
+ sys.version_info < (3, 6) or not use_builtin_scandir,
+ "Path-like objects have been introduced in Python 3.6",
+ )
def test_path_like(self):
self.assertTrue(isinstance(self.dir_entries[0], os.PathLike))
- self.assertEqual(self.os.path.join(self.scandir_path(), 'dir'),
- os.fspath(self.dir_entries[0]))
- self.assertEqual(self.os.path.join(self.scandir_path(), 'file'),
- os.fspath(self.dir_entries[1]))
+ self.assertEqual(
+ self.os.path.join(self.scandir_path(), "dir"),
+ os.fspath(self.dir_entries[0]),
+ )
+ self.assertEqual(
+ self.os.path.join(self.scandir_path(), "file"),
+ os.fspath(self.dir_entries[1]),
+ )
def test_non_existing_dir(self):
# behaves differently in different systems, so we skip the real fs test
self.skip_real_fs()
- self.assert_raises_os_error(
- errno.ENOENT, self.scandir, 'non_existing/fake_dir')
+ self.assert_raises_os_error(errno.ENOENT, self.scandir, "non_existing/fake_dir")
class RealScandirTest(FakeScandirTest):
@@ -5193,9 +5301,8 @@ class RealScandirRelTest(FakeScandirRelTest):
return True
-@unittest.skipIf(sys.version_info < (3, 7) or TestCase.is_windows or
- use_scandir_package,
- 'dir_fd support for os.scandir was introduced in Python 3.7')
+@unittest.skipIf(TestCase.is_windows, "dir_fd not supported for os.scandir in Windows")
+@unittest.skipIf(use_scandir_package, "no dir_fd support for scandir package")
class FakeScandirFdTest(FakeScandirTest):
def tearDown(self):
self.os.close(self.dir_fd)
@@ -5204,7 +5311,7 @@ class FakeScandirFdTest(FakeScandirTest):
def scandir_path(self):
# When scandir is called with a filedescriptor, only the name of the
# entry is returned in the path attribute of the DirEntry objects.
- return ''
+ return ""
def do_scandir(self):
self.dir_fd = self.os.open(self.directory, os.O_RDONLY)
@@ -5218,8 +5325,7 @@ class RealScandirFdTest(FakeScandirFdTest):
class FakeScandirFdRelTest(FakeScandirFdTest):
def do_scandir(self):
- self.dir_fd = self.os.open(self.os.path.relpath(self.directory),
- os.O_RDONLY)
+ self.dir_fd = self.os.open(self.os.path.relpath(self.directory), os.O_RDONLY)
return self.scandir(self.dir_fd)
@@ -5232,8 +5338,8 @@ class FakeExtendedAttributeTest(FakeOsModuleTestBase):
def setUp(self):
super(FakeExtendedAttributeTest, self).setUp()
self.check_linux_only()
- self.dir_path = self.make_path('foo')
- self.file_path = self.os.path.join(self.dir_path, 'bar')
+ self.dir_path = self.make_path("foo")
+ self.file_path = self.os.path.join(self.dir_path, "bar")
self.create_file(self.file_path)
def test_empty_xattr(self):
@@ -5241,63 +5347,182 @@ class FakeExtendedAttributeTest(FakeOsModuleTestBase):
self.assertEqual([], self.os.listxattr(self.file_path))
def test_setxattr(self):
- self.assertRaises(TypeError, self.os.setxattr,
- self.file_path, 'test', 'value')
- self.assert_raises_os_error(errno.EEXIST, self.os.setxattr,
- self.file_path, 'test', b'value',
- self.os.XATTR_REPLACE)
- self.os.setxattr(self.file_path, 'test', b'value')
- self.assertEqual(b'value', self.os.getxattr(self.file_path, 'test'))
- self.assert_raises_os_error(errno.ENODATA, self.os.setxattr,
- self.file_path, 'test', b'value',
- self.os.XATTR_CREATE)
+ self.assertRaises(TypeError, self.os.setxattr, self.file_path, "test", "value")
+ self.assert_raises_os_error(
+ errno.EEXIST,
+ self.os.setxattr,
+ self.file_path,
+ "test",
+ b"value",
+ self.os.XATTR_REPLACE,
+ )
+ self.os.setxattr(self.file_path, "test", b"value")
+ self.assertEqual(b"value", self.os.getxattr(self.file_path, "test"))
+ self.assert_raises_os_error(
+ errno.ENODATA,
+ self.os.setxattr,
+ self.file_path,
+ "test",
+ b"value",
+ self.os.XATTR_CREATE,
+ )
def test_removeattr(self):
- self.os.removexattr(self.file_path, 'test')
+ self.os.removexattr(self.file_path, "test")
self.assertEqual([], self.os.listxattr(self.file_path))
- self.os.setxattr(self.file_path, b'test', b'value')
- self.assertEqual(['test'], self.os.listxattr(self.file_path))
- self.assertEqual(b'value', self.os.getxattr(self.file_path, 'test'))
- self.os.removexattr(self.file_path, 'test')
+ self.os.setxattr(self.file_path, b"test", b"value")
+ self.assertEqual(["test"], self.os.listxattr(self.file_path))
+ self.assertEqual(b"value", self.os.getxattr(self.file_path, "test"))
+ self.os.removexattr(self.file_path, "test")
self.assertEqual([], self.os.listxattr(self.file_path))
- self.assertIsNone(self.os.getxattr(self.file_path, 'test'))
+ self.assertIsNone(self.os.getxattr(self.file_path, "test"))
def test_default_path(self):
self.os.chdir(self.dir_path)
- self.os.setxattr(self.dir_path, b'test', b'value')
- self.assertEqual(['test'], self.os.listxattr())
- self.assertEqual(b'value', self.os.getxattr(self.dir_path, 'test'))
+ self.os.setxattr(self.dir_path, b"test", b"value")
+ self.assertEqual(["test"], self.os.listxattr())
+ self.assertEqual(b"value", self.os.getxattr(self.dir_path, "test"))
class FakeOsUnreadableDirTest(FakeOsModuleTestBase):
def setUp(self):
if self.use_real_fs():
- # make sure no dir is created if skipped
+ # unreadable dirs in Windows are only simulated
+ # and cannot be created in the real OS using file system
+ # functions only
self.check_posix_only()
super(FakeOsUnreadableDirTest, self).setUp()
- self.check_posix_only()
- self.dir_path = self.make_path('some_dir')
- self.file_path = self.os.path.join(self.dir_path, 'some_file')
+ self.dir_path = self.make_path("some_dir")
+ self.file_path = self.os.path.join(self.dir_path, "some_file")
self.create_file(self.file_path)
- self.os.chmod(self.dir_path, 0o000)
+ self.chmod(self.dir_path, 0o000)
+
+ def chmod(self, path, mode):
+ if self.is_windows_fs:
+ self.filesystem.chmod(path, mode, force_unix_mode=True)
+ else:
+ self.os.chmod(path, mode)
+
+ def test_getuid(self):
+ self.skip_real_fs() # won't change user in real fs
+ self.check_posix_only()
+ uid = self.os.getuid()
+ set_uid(uid + 10)
+ self.assertEqual(uid + 10, self.os.getuid())
+ self.assertEqual(uid + 10, get_uid())
+ set_uid(uid)
+ self.assertEqual(uid, self.os.getuid())
+
+ def test_getgid(self):
+ self.skip_real_fs() # won't change group in real fs
+ self.check_posix_only()
+ gid = self.os.getgid()
+ set_gid(gid + 10)
+ self.assertEqual(gid + 10, self.os.getgid())
+ self.assertEqual(gid + 10, get_gid())
+ set_gid(gid)
+ self.assertEqual(gid, self.os.getgid())
def test_listdir_unreadable_dir(self):
if not is_root():
- self.assert_raises_os_error(
- errno.EACCES, self.os.listdir, self.dir_path)
+ self.assert_raises_os_error(errno.EACCES, self.os.listdir, self.dir_path)
else:
- self.assertEqual(['some_file'], self.os.listdir(self.dir_path))
+ self.assertEqual(["some_file"], self.os.listdir(self.dir_path))
+
+ def test_listdir_user_readable_dir(self):
+ self.chmod(self.dir_path, 0o600)
+ self.assertEqual(["some_file"], self.os.listdir(self.dir_path))
+ self.chmod(self.dir_path, 0o000)
+
+ def test_listdir_user_readable_dir_from_other_user(self):
+ self.skip_real_fs() # won't change user in real fs
+ self.check_posix_only()
+ user_id = get_uid()
+ set_uid(user_id + 1)
+ dir_path = self.make_path("dir1")
+ self.create_dir(dir_path, perm=0o600)
+ self.assertTrue(self.os.path.exists(dir_path))
+ set_uid(user_id)
+ if not is_root():
+ with self.assertRaises(PermissionError):
+ self.os.listdir(dir_path)
+ else:
+ self.assertEqual(["some_file"], self.os.listdir(self.dir_path))
+
+ def test_listdir_group_readable_dir_from_other_user(self):
+ self.skip_real_fs() # won't change user in real fs
+ user_id = get_uid()
+ set_uid(user_id + 1)
+ dir_path = self.make_path("dir1")
+ self.create_dir(dir_path, perm=0o660)
+ self.assertTrue(self.os.path.exists(dir_path))
+ set_uid(user_id)
+ self.assertEqual([], self.os.listdir(dir_path))
+
+ def test_listdir_group_readable_dir_from_other_group(self):
+ self.skip_real_fs() # won't change user in real fs
+ self.check_posix_only()
+ group_id = self.os.getgid()
+ set_gid(group_id + 1)
+ dir_path = self.make_path("dir1")
+ self.create_dir(dir_path, perm=0o060)
+ self.assertTrue(self.os.path.exists(dir_path))
+ set_gid(group_id)
+ if not is_root():
+ with self.assertRaises(PermissionError):
+ self.os.listdir(dir_path)
+ else:
+ self.assertEqual([], self.os.listdir(dir_path))
+
+ def test_listdir_other_readable_dir_from_other_group(self):
+ self.skip_real_fs() # won't change user in real fs
+ group_id = get_gid()
+ set_gid(group_id + 1)
+ dir_path = self.make_path("dir1")
+ self.create_dir(dir_path, perm=0o004)
+ self.assertTrue(self.os.path.exists(dir_path))
+ set_gid(group_id)
+ self.assertEqual([], self.os.listdir(dir_path))
def test_stat_unreadable_dir(self):
self.assertEqual(0, self.os.stat(self.dir_path).st_mode & 0o666)
+ def test_chmod_unreadable_dir(self):
+ self.chmod(self.dir_path, 0o666)
+ self.assertEqual(0o666, self.os.stat(self.dir_path).st_mode & 0o666)
+ self.chmod(self.dir_path, 0o000)
+ self.assertEqual(0, self.os.stat(self.dir_path).st_mode & 0o666)
+
def test_stat_file_in_unreadable_dir(self):
if not is_root():
- self.assert_raises_os_error(
- errno.EACCES, self.os.stat, self.file_path)
+ self.assert_raises_os_error(errno.EACCES, self.os.stat, self.file_path)
else:
self.assertEqual(0, self.os.stat(self.file_path).st_size)
+ def test_remove_unreadable_dir(self):
+ self.check_posix_only()
+ dir_path = self.make_path("dir1")
+ self.create_dir(dir_path, perm=0o000)
+ self.assertTrue(self.os.path.exists(dir_path))
+ self.os.rmdir(dir_path)
+ self.assertFalse(self.os.path.exists(dir_path))
+
+ def test_remove_unreadable_dir_from_other_user(self):
+ self.skip_real_fs() # won't change user in real fs
+ user_id = get_uid()
+ set_uid(user_id + 1)
+ dir_path = self.make_path("dir1")
+ self.create_dir(dir_path, perm=0o000)
+ self.assertTrue(self.os.path.exists(dir_path))
+ set_uid(user_id)
+ if not is_root():
+ with self.assertRaises(PermissionError):
+ self.os.rmdir(dir_path)
+ self.assertTrue(self.os.path.exists(dir_path))
+ else:
+ self.os.rmdir(dir_path)
+ self.assertFalse(self.os.path.exists(dir_path))
+
class RealOsUnreadableDirTest(FakeOsUnreadableDirTest):
def use_real_fs(self):
diff --git a/pyfakefs/tests/fake_pathlib_test.py b/pyfakefs/tests/fake_pathlib_test.py
index 1a3cdfc..12820ba 100644
--- a/pyfakefs/tests/fake_pathlib_test.py
+++ b/pyfakefs/tests/fake_pathlib_test.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -26,33 +25,46 @@ import pathlib
import stat
import sys
import unittest
+from collections import namedtuple
+from unittest import mock
+from unittest.mock import patch
-from pyfakefs.fake_filesystem import is_root
+from pyfakefs import fake_pathlib, fake_filesystem, fake_filesystem_unittest, fake_os
+from pyfakefs.fake_filesystem import OSType
+from pyfakefs.helpers import IS_PYPY, is_root
+from pyfakefs.tests.test_utils import RealFsTestMixin
-from pyfakefs import fake_pathlib, fake_filesystem
-from pyfakefs.helpers import IS_PYPY
-from pyfakefs.tests.test_utils import RealFsTestCase
+is_windows = sys.platform == "win32"
-is_windows = sys.platform == 'win32'
+class RealPathlibTestCase(fake_filesystem_unittest.TestCase, RealFsTestMixin):
+ is_windows = sys.platform == "win32"
-class RealPathlibTestCase(RealFsTestCase):
- def __init__(self, methodName='runTest'):
- super(RealPathlibTestCase, self).__init__(methodName)
- self.pathlib = pathlib
- self.path = None
+ def __init__(self, methodName="runTest"):
+ fake_filesystem_unittest.TestCase.__init__(self, methodName)
+ RealFsTestMixin.__init__(self)
def setUp(self):
- super().setUp()
+ RealFsTestMixin.setUp(self)
+ self.filesystem = None
+ self.real_os = os
if not self.use_real_fs():
- self.pathlib = fake_pathlib.FakePathlibModule(self.filesystem)
- self.path = self.pathlib.Path
+ self.setUpPyfakefs()
+ self.filesystem = self.fs
+ self.create_basepath()
+ self.pathlib = pathlib
+ self.path = pathlib.Path
+ self.os = os
+ self.open = open
+
+ def use_real_fs(self):
+ return False
class FakePathlibInitializationTest(RealPathlibTestCase):
def test_initialization_type(self):
"""Make sure tests for class type will work"""
- path = self.path('/test')
+ path = self.path("/test")
if is_windows:
self.assertTrue(isinstance(path, self.pathlib.WindowsPath))
self.assertTrue(isinstance(path, self.pathlib.PureWindowsPath))
@@ -74,54 +86,56 @@ class FakePathlibInitializationTest(RealPathlibTestCase):
self.assertTrue(self.pathlib.WindowsPath())
def test_init_with_segments(self):
- """Basic initialization tests - taken from pathlib.Path documentation
+ """Basic initialization tests - taken from
+ pathlib.Path documentation.
"""
- self.assertEqual(self.path('/', 'foo', 'bar', 'baz'),
- self.path('/foo/bar/baz'))
- self.assertEqual(self.path(), self.path('.'))
- self.assertEqual(self.path(self.path('foo'), self.path('bar')),
- self.path('foo/bar'))
- self.assertEqual(self.path('/etc') / 'init.d' / 'reboot',
- self.path('/etc/init.d/reboot'))
+ self.assertEqual(self.path("/", "foo", "bar", "baz"), self.path("/foo/bar/baz"))
+ self.assertEqual(self.path(), self.path("."))
+ self.assertEqual(
+ self.path(self.path("foo"), self.path("bar")), self.path("foo/bar")
+ )
+ self.assertEqual(
+ self.path("/etc") / "init.d" / "reboot",
+ self.path("/etc/init.d/reboot"),
+ )
def test_init_collapse(self):
"""Tests for collapsing path during initialization.
Taken from pathlib.PurePath documentation.
"""
- self.assertEqual(self.path('foo//bar'), self.path('foo/bar'))
- self.assertEqual(self.path('foo/./bar'), self.path('foo/bar'))
- self.assertNotEqual(self.path('foo/../bar'), self.path('foo/bar'))
- self.assertEqual(self.path('/etc', '/usr', 'lib64'),
- self.path('/usr/lib64'))
+ self.assertEqual(self.path("foo//bar"), self.path("foo/bar"))
+ self.assertEqual(self.path("foo/./bar"), self.path("foo/bar"))
+ self.assertNotEqual(self.path("foo/../bar"), self.path("foo/bar"))
+ self.assertEqual(self.path("/etc", "/usr", "lib64"), self.path("/usr/lib64"))
def test_path_parts(self):
sep = self.os.path.sep
- path = self.path(sep + self.os.path.join('foo', 'bar', 'setup.py'))
- self.assertEqual(path.parts, (sep, 'foo', 'bar', 'setup.py'))
- self.assertEqual(path.drive, '')
+ path = self.path(sep + self.os.path.join("foo", "bar", "setup.py"))
+ self.assertEqual(path.parts, (sep, "foo", "bar", "setup.py"))
+ self.assertEqual(path.drive, "")
self.assertEqual(path.root, sep)
self.assertEqual(path.anchor, sep)
- self.assertEqual(path.name, 'setup.py')
- self.assertEqual(path.stem, 'setup')
- self.assertEqual(path.suffix, '.py')
- self.assertEqual(path.parent,
- self.path(sep + self.os.path.join('foo', 'bar')))
- self.assertEqual(path.parents[0],
- self.path(sep + self.os.path.join('foo', 'bar')))
- self.assertEqual(path.parents[1], self.path(sep + 'foo'))
+ self.assertEqual(path.name, "setup.py")
+ self.assertEqual(path.stem, "setup")
+ self.assertEqual(path.suffix, ".py")
+ self.assertEqual(path.parent, self.path(sep + self.os.path.join("foo", "bar")))
+ self.assertEqual(
+ path.parents[0], self.path(sep + self.os.path.join("foo", "bar"))
+ )
+ self.assertEqual(path.parents[1], self.path(sep + "foo"))
self.assertEqual(path.parents[2], self.path(sep))
- @unittest.skipIf(is_windows, 'POSIX specific behavior')
+ @unittest.skipIf(is_windows, "POSIX specific behavior")
def test_is_absolute_posix(self):
- self.assertTrue(self.path('/a/b').is_absolute())
- self.assertFalse(self.path('a/b').is_absolute())
- self.assertFalse(self.path('d:/b').is_absolute())
+ self.assertTrue(self.path("/a/b").is_absolute())
+ self.assertFalse(self.path("a/b").is_absolute())
+ self.assertFalse(self.path("d:/b").is_absolute())
- @unittest.skipIf(not is_windows, 'Windows specific behavior')
+ @unittest.skipIf(not is_windows, "Windows specific behavior")
def test_is_absolute_windows(self):
- self.assertFalse(self.path('/a/b').is_absolute())
- self.assertFalse(self.path('a/b').is_absolute())
- self.assertTrue(self.path('d:/b').is_absolute())
+ self.assertFalse(self.path("/a/b").is_absolute())
+ self.assertFalse(self.path("a/b").is_absolute())
+ self.assertTrue(self.path("d:/b").is_absolute())
class RealPathlibInitializationTest(FakePathlibInitializationTest):
@@ -129,56 +143,60 @@ class RealPathlibInitializationTest(FakePathlibInitializationTest):
return True
-@unittest.skipIf(not is_windows, 'Windows specific behavior')
+@unittest.skipIf(not is_windows, "Windows specific behavior")
class FakePathlibInitializationWithDriveTest(RealPathlibTestCase):
def test_init_with_segments(self):
"""Basic initialization tests - taken from pathlib.Path
documentation"""
- self.assertEqual(self.path('c:/', 'foo', 'bar', 'baz'),
- self.path('c:/foo/bar/baz'))
- self.assertEqual(self.path(), self.path('.'))
- self.assertEqual(self.path(self.path('foo'), self.path('bar')),
- self.path('foo/bar'))
- self.assertEqual(self.path('c:/Users') / 'john' / 'data',
- self.path('c:/Users/john/data'))
+ self.assertEqual(
+ self.path("c:/", "foo", "bar", "baz"), self.path("c:/foo/bar/baz")
+ )
+ self.assertEqual(self.path(), self.path("."))
+ self.assertEqual(
+ self.path(self.path("foo"), self.path("bar")), self.path("foo/bar")
+ )
+ self.assertEqual(
+ self.path("c:/Users") / "john" / "data",
+ self.path("c:/Users/john/data"),
+ )
def test_init_collapse(self):
"""Tests for collapsing path during initialization.
Taken from pathlib.PurePath documentation.
"""
- self.assertEqual(self.path('c:/Windows', 'd:bar'),
- self.path('d:bar'))
- self.assertEqual(self.path('c:/Windows', '/Program Files'),
- self.path('c:/Program Files'))
+ self.assertEqual(self.path("c:/Windows", "d:bar"), self.path("d:bar"))
+ self.assertEqual(
+ self.path("c:/Windows", "/Program Files"),
+ self.path("c:/Program Files"),
+ )
def test_path_parts(self):
- path = self.path(
- self.os.path.join('d:', 'python scripts', 'setup.py'))
- self.assertEqual(path.parts, ('d:', 'python scripts', 'setup.py'))
- self.assertEqual(path.drive, 'd:')
- self.assertEqual(path.root, '')
- self.assertEqual(path.anchor, 'd:')
- self.assertEqual(path.name, 'setup.py')
- self.assertEqual(path.stem, 'setup')
- self.assertEqual(path.suffix, '.py')
- self.assertEqual(path.parent,
- self.path(
- self.os.path.join('d:', 'python scripts')))
- self.assertEqual(path.parents[0],
- self.path(
- self.os.path.join('d:', 'python scripts')))
- self.assertEqual(path.parents[1], self.path('d:'))
-
- @unittest.skipIf(not is_windows, 'Windows-specifc behavior')
+ path = self.path(self.os.path.join("d:", "python scripts", "setup.py"))
+ self.assertEqual(path.parts, ("d:", "python scripts", "setup.py"))
+ self.assertEqual(path.drive, "d:")
+ self.assertEqual(path.root, "")
+ self.assertEqual(path.anchor, "d:")
+ self.assertEqual(path.name, "setup.py")
+ self.assertEqual(path.stem, "setup")
+ self.assertEqual(path.suffix, ".py")
+ self.assertEqual(
+ path.parent, self.path(self.os.path.join("d:", "python scripts"))
+ )
+ self.assertEqual(
+ path.parents[0],
+ self.path(self.os.path.join("d:", "python scripts")),
+ )
+ self.assertEqual(path.parents[1], self.path("d:"))
+
+ @unittest.skipIf(not is_windows, "Windows-specifc behavior")
def test_is_absolute(self):
- self.assertTrue(self.path('c:/a/b').is_absolute())
- self.assertFalse(self.path('/a/b').is_absolute())
- self.assertFalse(self.path('c:').is_absolute())
- self.assertTrue(self.path('//some/share').is_absolute())
+ self.assertTrue(self.path("c:/a/b").is_absolute())
+ self.assertFalse(self.path("/a/b").is_absolute())
+ self.assertFalse(self.path("c:").is_absolute())
+ self.assertTrue(self.path("//some/share").is_absolute())
-class RealPathlibInitializationWithDriveTest(
- FakePathlibInitializationWithDriveTest):
+class RealPathlibInitializationWithDriveTest(FakePathlibInitializationWithDriveTest):
def use_real_fs(self):
return True
@@ -186,70 +204,78 @@ class RealPathlibInitializationWithDriveTest(
class FakePathlibPurePathTest(RealPathlibTestCase):
"""Tests functionality present in PurePath class."""
- @unittest.skipIf(is_windows, 'POSIX specific behavior')
def test_is_reserved_posix(self):
- self.assertFalse(self.path('/dev').is_reserved())
- self.assertFalse(self.path('/').is_reserved())
- self.assertFalse(self.path('COM1').is_reserved())
- self.assertFalse(self.path('nul.txt').is_reserved())
+ self.check_posix_only()
+ self.assertFalse(self.path("/dev").is_reserved())
+ self.assertFalse(self.path("/").is_reserved())
+ self.assertFalse(self.path("COM1").is_reserved())
+ self.assertFalse(self.path("nul.txt").is_reserved())
- @unittest.skipIf(not is_windows, 'Windows specific behavior')
+ @unittest.skipIf(not is_windows, "Windows specific behavior")
def test_is_reserved_windows(self):
self.check_windows_only()
- self.assertFalse(self.path('/dev').is_reserved())
- self.assertFalse(self.path('/').is_reserved())
- self.assertTrue(self.path('COM1').is_reserved())
- self.assertTrue(self.path('nul.txt').is_reserved())
+ self.assertFalse(self.path("/dev").is_reserved())
+ self.assertFalse(self.path("/").is_reserved())
+ self.assertTrue(self.path("COM1").is_reserved())
+ self.assertTrue(self.path("nul.txt").is_reserved())
def test_joinpath(self):
- self.assertEqual(self.path('/etc').joinpath('passwd'),
- self.path('/etc/passwd'))
- self.assertEqual(self.path('/etc').joinpath(self.path('passwd')),
- self.path('/etc/passwd'))
- self.assertEqual(self.path('/foo').joinpath('bar', 'baz'),
- self.path('/foo/bar/baz'))
+ self.assertEqual(self.path("/etc").joinpath("passwd"), self.path("/etc/passwd"))
+ self.assertEqual(
+ self.path("/etc").joinpath(self.path("passwd")),
+ self.path("/etc/passwd"),
+ )
+ self.assertEqual(
+ self.path("/foo").joinpath("bar", "baz"), self.path("/foo/bar/baz")
+ )
def test_joinpath_drive(self):
self.check_windows_only()
- self.assertEqual(self.path('c:').joinpath('/Program Files'),
- self.path('c:/Program Files'))
+ self.assertEqual(
+ self.path("c:").joinpath("/Program Files"),
+ self.path("c:/Program Files"),
+ )
def test_match(self):
- self.assertTrue(self.path('a/b.py').match('*.py'))
- self.assertTrue(self.path('/a/b/c.py').match('b/*.py'))
- self.assertFalse(self.path('/a/b/c.py').match('a/*.py'))
- self.assertTrue(self.path('/a.py').match('/*.py'))
- self.assertFalse(self.path('a/b.py').match('/*.py'))
+ self.assertTrue(self.path("a/b.py").match("*.py"))
+ self.assertTrue(self.path("/a/b/c.py").match("b/*.py"))
+ self.assertFalse(self.path("/a/b/c.py").match("a/*.py"))
+ self.assertTrue(self.path("/a.py").match("/*.py"))
+ self.assertFalse(self.path("a/b.py").match("/*.py"))
def test_relative_to(self):
- self.assertEqual(self.path('/etc/passwd').relative_to('/'),
- self.path('etc/passwd'))
- self.assertEqual(self.path('/etc/passwd').relative_to('/'),
- self.path('etc/passwd'))
+ self.assertEqual(
+ self.path("/etc/passwd").relative_to("/"), self.path("etc/passwd")
+ )
+ self.assertEqual(
+ self.path("/etc/passwd").relative_to("/"), self.path("etc/passwd")
+ )
with self.assertRaises(ValueError):
- self.path('passwd').relative_to('/usr')
+ self.path("passwd").relative_to("/usr")
- @unittest.skipIf(sys.version_info < (3, 9),
- 'is_relative_to new in Python 3.9')
+ @unittest.skipIf(sys.version_info < (3, 9), "is_relative_to new in Python 3.9")
def test_is_relative_to(self):
- path = self.path('/etc/passwd')
- self.assertTrue(path.is_relative_to('/etc'))
- self.assertFalse(path.is_relative_to('/src'))
+ path = self.path("/etc/passwd")
+ self.assertTrue(path.is_relative_to("/etc"))
+ self.assertFalse(path.is_relative_to("/src"))
def test_with_name(self):
self.check_windows_only()
self.assertEqual(
- self.path('c:/Downloads/pathlib.tar.gz').with_name('setup.py'),
- self.path('c:/Downloads/setup.py'))
+ self.path("c:/Downloads/pathlib.tar.gz").with_name("setup.py"),
+ self.path("c:/Downloads/setup.py"),
+ )
with self.assertRaises(ValueError):
- self.path('c:/').with_name('setup.py')
+ self.path("c:/").with_name("setup.py")
def test_with_suffix(self):
self.assertEqual(
- self.path('c:/Downloads/pathlib.tar.gz').with_suffix('.bz2'),
- self.path('c:/Downloads/pathlib.tar.bz2'))
- self.assertEqual(self.path('README').with_suffix('.txt'),
- self.path('README.txt'))
+ self.path("c:/Downloads/pathlib.tar.gz").with_suffix(".bz2"),
+ self.path("c:/Downloads/pathlib.tar.bz2"),
+ )
+ self.assertEqual(
+ self.path("README").with_suffix(".txt"), self.path("README.txt")
+ )
class RealPathlibPurePathTest(FakePathlibPurePathTest):
@@ -260,82 +286,60 @@ class RealPathlibPurePathTest(FakePathlibPurePathTest):
class FakePathlibFileObjectPropertyTest(RealPathlibTestCase):
def setUp(self):
super(FakePathlibFileObjectPropertyTest, self).setUp()
- self.file_path = self.make_path('home', 'jane', 'test.py')
- self.create_file(self.file_path, contents=b'a' * 100)
- self.create_dir(self.make_path('home', 'john'))
+ self.file_path = self.make_path("home", "jane", "test.py")
+ self.create_file(self.file_path, contents=b"a" * 100)
+ self.create_dir(self.make_path("home", "john"))
try:
self.skip_if_symlink_not_supported()
except unittest.SkipTest:
return
- self.create_symlink(self.make_path('john'),
- self.make_path('home', 'john'))
- self.file_link_path = self.make_path('test.py')
+ self.create_symlink(self.make_path("john"), self.make_path("home", "john"))
+ self.file_link_path = self.make_path("test.py")
self.create_symlink(self.file_link_path, self.file_path)
- self.create_symlink(self.make_path('broken_dir_link'),
- self.make_path('home', 'none'))
- self.create_symlink(self.make_path('broken_file_link'),
- self.make_path('home', 'none', 'test.py'))
+ self.create_symlink(
+ self.make_path("broken_dir_link"), self.make_path("home", "none")
+ )
+ self.create_symlink(
+ self.make_path("broken_file_link"),
+ self.make_path("home", "none", "test.py"),
+ )
def test_exists(self):
self.skip_if_symlink_not_supported()
self.assertTrue(self.path(self.file_path).exists())
- self.assertTrue(self.path(
- self.make_path('home', 'jane')).exists())
- self.assertFalse(self.path(
- self.make_path('home', 'jane', 'test')).exists())
- self.assertTrue(self.path(
- self.make_path('john')).exists())
- self.assertTrue(self.path(
- self.file_link_path).exists())
- self.assertFalse(self.path(
- self.make_path('broken_dir_link')).exists())
- self.assertFalse(self.path(
- self.make_path('broken_file_link')).exists())
+ self.assertTrue(self.path(self.make_path("home", "jane")).exists())
+ self.assertFalse(self.path(self.make_path("home", "jane", "test")).exists())
+ self.assertTrue(self.path(self.make_path("john")).exists())
+ self.assertTrue(self.path(self.file_link_path).exists())
+ self.assertFalse(self.path(self.make_path("broken_dir_link")).exists())
+ self.assertFalse(self.path(self.make_path("broken_file_link")).exists())
def test_is_dir(self):
self.skip_if_symlink_not_supported()
- self.assertFalse(self.path(
- self.file_path).is_dir())
- self.assertTrue(self.path(
- self.make_path('home/jane')).is_dir())
- self.assertTrue(self.path(
- self.make_path('john')).is_dir())
- self.assertFalse(self.path(
- self.file_link_path).is_dir())
- self.assertFalse(self.path(
- self.make_path('broken_dir_link')).is_dir())
- self.assertFalse(self.path(
- self.make_path('broken_file_link')).is_dir())
+ self.assertFalse(self.path(self.file_path).is_dir())
+ self.assertTrue(self.path(self.make_path("home/jane")).is_dir())
+ self.assertTrue(self.path(self.make_path("john")).is_dir())
+ self.assertFalse(self.path(self.file_link_path).is_dir())
+ self.assertFalse(self.path(self.make_path("broken_dir_link")).is_dir())
+ self.assertFalse(self.path(self.make_path("broken_file_link")).is_dir())
def test_is_file(self):
self.skip_if_symlink_not_supported()
- self.assertTrue(self.path(
- self.make_path('home/jane/test.py')).is_file())
- self.assertFalse(self.path(
- self.make_path('home/jane')).is_file())
- self.assertFalse(self.path(
- self.make_path('john')).is_file())
- self.assertTrue(self.path(
- self.file_link_path).is_file())
- self.assertFalse(self.path(
- self.make_path('broken_dir_link')).is_file())
- self.assertFalse(self.path(
- self.make_path('broken_file_link')).is_file())
+ self.assertTrue(self.path(self.make_path("home/jane/test.py")).is_file())
+ self.assertFalse(self.path(self.make_path("home/jane")).is_file())
+ self.assertFalse(self.path(self.make_path("john")).is_file())
+ self.assertTrue(self.path(self.file_link_path).is_file())
+ self.assertFalse(self.path(self.make_path("broken_dir_link")).is_file())
+ self.assertFalse(self.path(self.make_path("broken_file_link")).is_file())
def test_is_symlink(self):
self.skip_if_symlink_not_supported()
- self.assertFalse(self.path(
- self.make_path('home/jane/test.py')).is_symlink())
- self.assertFalse(self.path(
- self.make_path('home/jane')).is_symlink())
- self.assertTrue(self.path(
- self.make_path('john')).is_symlink())
- self.assertTrue(self.path(
- self.file_link_path).is_symlink())
- self.assertTrue(self.path(
- self.make_path('broken_dir_link')).is_symlink())
- self.assertTrue(self.path(
- self.make_path('broken_file_link')).is_symlink())
+ self.assertFalse(self.path(self.make_path("home/jane/test.py")).is_symlink())
+ self.assertFalse(self.path(self.make_path("home/jane")).is_symlink())
+ self.assertTrue(self.path(self.make_path("john")).is_symlink())
+ self.assertTrue(self.path(self.file_link_path).is_symlink())
+ self.assertTrue(self.path(self.make_path("broken_dir_link")).is_symlink())
+ self.assertTrue(self.path(self.make_path("broken_file_link")).is_symlink())
def test_stat(self):
self.skip_if_symlink_not_supported()
@@ -347,8 +351,7 @@ class FakePathlibFileObjectPropertyTest(RealPathlibTestCase):
self.assertEqual(stat_result.st_ino, file_stat.st_ino)
self.assertEqual(stat_result.st_size, 100)
self.assertEqual(stat_result.st_mtime, file_stat.st_mtime)
- self.assertEqual(stat_result[stat.ST_MTIME],
- int(file_stat.st_mtime))
+ self.assertEqual(stat_result[stat.ST_MTIME], int(file_stat.st_mtime))
def check_lstat(self, expected_size):
self.skip_if_symlink_not_supported()
@@ -361,16 +364,16 @@ class FakePathlibFileObjectPropertyTest(RealPathlibTestCase):
self.assertEqual(stat_result.st_size, expected_size)
self.assertEqual(stat_result.st_mtime, link_stat.st_mtime)
- @unittest.skipIf(is_windows, 'POSIX specific behavior')
+ @unittest.skipIf(is_windows, "POSIX specific behavior")
def test_lstat_posix(self):
self.check_lstat(len(self.file_path))
- @unittest.skipIf(not is_windows, 'Windows specific behavior')
+ @unittest.skipIf(not is_windows, "Windows specific behavior")
def test_lstat_windows(self):
self.skip_if_symlink_not_supported()
self.check_lstat(0)
- @unittest.skipIf(is_windows, 'Linux specific behavior')
+ @unittest.skipIf(is_windows, "Linux specific behavior")
def test_chmod(self):
self.check_linux_only()
file_stat = self.os.stat(self.file_path)
@@ -383,103 +386,107 @@ class FakePathlibFileObjectPropertyTest(RealPathlibTestCase):
self.skip_if_symlink_not_supported()
file_stat = self.os.stat(self.file_path)
link_stat = self.os.lstat(self.file_link_path)
- if not hasattr(os, "lchmod"):
+ if not hasattr(self.real_os, "lchmod"):
with self.assertRaises(NotImplementedError):
self.path(self.file_link_path).lchmod(0o444)
else:
self.path(self.file_link_path).lchmod(0o444)
self.assertEqual(file_stat.st_mode, stat.S_IFREG | 0o666)
# the exact mode depends on OS and Python version
- self.assertEqual(link_stat.st_mode & 0o777700,
- stat.S_IFLNK | 0o700)
+ self.assertEqual(link_stat.st_mode & 0o777700, stat.S_IFLNK | 0o700)
- @unittest.skipIf(sys.version_info < (3, 10),
- "follow_symlinks argument new in Python 3.10")
+ @unittest.skipIf(
+ sys.version_info < (3, 10),
+ "follow_symlinks argument new in Python 3.10",
+ )
def test_chmod_no_followsymlinks(self):
self.skip_if_symlink_not_supported()
file_stat = self.os.stat(self.file_path)
link_stat = self.os.lstat(self.file_link_path)
- if os.chmod not in os.supports_follow_symlinks or IS_PYPY:
+ if self.os.chmod not in self.os.supports_follow_symlinks or IS_PYPY:
with self.assertRaises(NotImplementedError):
- self.path(self.file_link_path).chmod(0o444,
- follow_symlinks=False)
+ self.path(self.file_link_path).chmod(0o444, follow_symlinks=False)
else:
self.path(self.file_link_path).chmod(0o444, follow_symlinks=False)
self.assertEqual(file_stat.st_mode, stat.S_IFREG | 0o666)
# the exact mode depends on OS and Python version
- self.assertEqual(link_stat.st_mode & 0o777700,
- stat.S_IFLNK | 0o700)
+ self.assertEqual(link_stat.st_mode & 0o777700, stat.S_IFLNK | 0o700)
def test_resolve(self):
- self.create_dir(self.make_path('antoine', 'docs'))
- self.create_file(self.make_path('antoine', 'setup.py'))
- self.os.chdir(self.make_path('antoine'))
+ self.create_dir(self.make_path("antoine", "docs"))
+ self.create_file(self.make_path("antoine", "setup.py"))
+ self.os.chdir(self.make_path("antoine"))
# use real path to handle symlink /var to /private/var in MacOs
- self.assert_equal_paths(self.path().resolve(),
- self.path(self.os.path.realpath(
- self.make_path('antoine'))))
self.assert_equal_paths(
- self.path(
- self.os.path.join('docs', '..', 'setup.py')).resolve(),
- self.path(
- self.os.path.realpath(
- self.make_path('antoine', 'setup.py'))))
+ self.path().resolve(),
+ self.path(self.os.path.realpath(self.make_path("antoine"))),
+ )
+ self.assert_equal_paths(
+ self.path(self.os.path.join("docs", "..", "setup.py")).resolve(),
+ self.path(self.os.path.realpath(self.make_path("antoine", "setup.py"))),
+ )
def test_stat_file_in_unreadable_dir(self):
self.check_posix_only()
- dir_path = self.make_path('some_dir')
- file_path = self.os.path.join(dir_path, 'some_file')
+ dir_path = self.make_path("some_dir")
+ file_path = self.os.path.join(dir_path, "some_file")
self.create_file(file_path)
self.os.chmod(dir_path, 0o000)
if not is_root():
- self.assert_raises_os_error(
- errno.EACCES, self.path(file_path).stat)
+ self.assert_raises_os_error(errno.EACCES, self.path(file_path).stat)
else:
self.assertEqual(0, self.path(file_path).stat().st_size)
def test_iterdir_in_unreadable_dir(self):
self.check_posix_only()
- dir_path = self.make_path('some_dir')
- file_path = self.os.path.join(dir_path, 'some_file')
+ dir_path = self.make_path("some_dir")
+ file_path = self.os.path.join(dir_path, "some_file")
self.create_file(file_path)
self.os.chmod(dir_path, 0o000)
- iter = self.path(dir_path).iterdir()
+ it = self.path(dir_path).iterdir()
if not is_root():
- self.assert_raises_os_error(errno.EACCES, list, iter)
+ self.assert_raises_os_error(errno.EACCES, list, it)
else:
- path = str(list(iter)[0])
- self.assertTrue(path.endswith('some_file'))
+ path = str(list(it)[0])
+ self.assertTrue(path.endswith("some_file"))
def test_resolve_nonexisting_file(self):
- path = self.path(
- self.make_path('/path', 'to', 'file', 'this can not exist'))
+ path = self.path(self.make_path("/path", "to", "file", "this can not exist"))
self.assertEqual(path, path.resolve())
def test_cwd(self):
- dir_path = self.make_path('jane')
+ dir_path = self.make_path("jane")
self.create_dir(dir_path)
self.os.chdir(dir_path)
- self.assert_equal_paths(self.path.cwd(),
- self.path(self.os.path.realpath(dir_path)))
+ self.assert_equal_paths(
+ self.path.cwd(), self.path(self.os.path.realpath(dir_path))
+ )
- def test_expanduser(self):
- if is_windows:
- self.assertEqual(self.path('~').expanduser(),
- self.path(
- os.environ['USERPROFILE'].replace('\\',
- '/')))
- else:
- self.assertEqual(self.path('~').expanduser(),
- self.path(os.environ['HOME']))
+ @unittest.skipIf(sys.platform != "win32", "Windows specific test")
+ @patch.dict(os.environ, {"USERPROFILE": r"C:\Users\John"})
+ def test_expanduser_windows(self):
+ self.assertEqual(
+ self.path("~").expanduser(),
+ self.path("C:/Users/John"),
+ )
+
+ @unittest.skipIf(sys.platform == "win32", "Posix specific test")
+ @patch.dict(os.environ, {"HOME": "/home/john"})
+ def test_expanduser_posix(self):
+ self.assertEqual(self.path("~").expanduser(), self.path("/home/john"))
+
+ @unittest.skipIf(sys.platform != "win32", "Windows specific test")
+ @patch.dict(os.environ, {"USERPROFILE": r"C:\Users\John"})
+ def test_home_windows(self):
+ self.assertEqual(
+ self.path(self.path("C:/Users/John")),
+ self.path.home(),
+ )
- def test_home(self):
- if is_windows:
- self.assertEqual(self.path(
- os.environ['USERPROFILE'].replace('\\', '/')),
- self.path.home())
- else:
- self.assertEqual(self.path(os.environ['HOME']),
- self.path.home())
+ @unittest.skipIf(sys.platform == "win32", "Posix specific test")
+ @patch.dict(os.environ, {"HOME": "/home/john"})
+ def test_home_posix(self):
+ self.assertEqual(self.path("/home/john"), self.path.home())
class RealPathlibFileObjectPropertyTest(FakePathlibFileObjectPropertyTest):
@@ -492,265 +499,271 @@ class FakePathlibPathFileOperationTest(RealPathlibTestCase):
def test_exists(self):
self.skip_if_symlink_not_supported()
- self.create_file(self.make_path('home', 'jane', 'test.py'))
- self.create_dir(self.make_path('home', 'john'))
- self.create_symlink(
- self.make_path('john'), self.make_path('home', 'john'))
- self.create_symlink(
- self.make_path('none'), self.make_path('home', 'none'))
+ self.create_file(self.make_path("home", "jane", "test.py"))
+ self.create_dir(self.make_path("home", "john"))
+ self.create_symlink(self.make_path("john"), self.make_path("home", "john"))
+ self.create_symlink(self.make_path("none"), self.make_path("home", "none"))
- self.assertTrue(
- self.path(self.make_path('home', 'jane', 'test.py')).exists())
- self.assertTrue(self.path(self.make_path('home', 'jane')).exists())
- self.assertTrue(self.path(self.make_path('john')).exists())
- self.assertFalse(self.path(self.make_path('none')).exists())
- self.assertFalse(
- self.path(self.make_path('home', 'jane', 'test')).exists())
+ self.assertTrue(self.path(self.make_path("home", "jane", "test.py")).exists())
+ self.assertTrue(self.path(self.make_path("home", "jane")).exists())
+ self.assertTrue(self.path(self.make_path("john")).exists())
+ self.assertFalse(self.path(self.make_path("none")).exists())
+ self.assertFalse(self.path(self.make_path("home", "jane", "test")).exists())
def test_open(self):
- self.create_dir(self.make_path('foo'))
+ self.create_dir(self.make_path("foo"))
with self.assertRaises(OSError):
- self.path(self.make_path('foo', 'bar.txt')).open()
- self.path(self.make_path('foo', 'bar.txt')).open('w').close()
- self.assertTrue(
- self.os.path.exists(self.make_path('foo', 'bar.txt')))
+ self.path(self.make_path("foo", "bar.txt")).open()
+ self.path(self.make_path("foo", "bar.txt")).open("w").close()
+ self.assertTrue(self.os.path.exists(self.make_path("foo", "bar.txt")))
def test_read_text(self):
- self.create_file(self.make_path('text_file'), contents='foo')
- file_path = self.path(self.make_path('text_file'))
- self.assertEqual(file_path.read_text(), 'foo')
+ self.create_file(self.make_path("text_file"), contents="foo")
+ file_path = self.path(self.make_path("text_file"))
+ self.assertEqual(file_path.read_text(), "foo")
+
+ @unittest.skipIf(
+ sys.version_info < (3, 12),
+ "is_junction method new in Python 3.12",
+ )
+ def test_is_junction(self):
+ self.create_file(self.make_path("text_file"), contents="foo")
+ file_path = self.path(self.make_path("text_file"))
+ self.assertFalse(file_path.is_junction())
def test_read_text_with_encoding(self):
- self.create_file(self.make_path('text_file'),
- contents='ерунда', encoding='cyrillic')
- file_path = self.path(self.make_path('text_file'))
- self.assertEqual(file_path.read_text(encoding='cyrillic'),
- 'ерунда')
+ self.create_file(
+ self.make_path("text_file"), contents="ерунда", encoding="cyrillic"
+ )
+ file_path = self.path(self.make_path("text_file"))
+ self.assertEqual(file_path.read_text(encoding="cyrillic"), "ерунда")
def test_write_text(self):
- path_name = self.make_path('text_file')
+ path_name = self.make_path("text_file")
file_path = self.path(path_name)
- file_path.write_text(str('foo'))
+ file_path.write_text(str("foo"))
self.assertTrue(self.os.path.exists(path_name))
- self.check_contents(path_name, 'foo')
+ self.check_contents(path_name, "foo")
def test_write_text_with_encoding(self):
- path_name = self.make_path('text_file')
+ path_name = self.make_path("text_file")
file_path = self.path(path_name)
- file_path.write_text('ανοησίες', encoding='greek')
+ file_path.write_text("ανοησίες", encoding="greek")
self.assertTrue(self.os.path.exists(path_name))
- self.check_contents(path_name, 'ανοησίες'.encode('greek'))
+ self.check_contents(path_name, "ανοησίες".encode("greek"))
- @unittest.skipIf(sys.version_info < (3, 10),
- "newline argument new in Python 3.10")
+ @unittest.skipIf(sys.version_info < (3, 10), "newline argument new in Python 3.10")
def test_write_with_newline_arg(self):
- path = self.path(self.make_path('some_file'))
- path.write_text('1\r\n2\n3\r4', newline='')
- self.check_contents(path, b'1\r\n2\n3\r4')
- path.write_text('1\r\n2\n3\r4', newline='\n')
- self.check_contents(path, b'1\r\n2\n3\r4')
- path.write_text('1\r\n2\n3\r4', newline='\r\n')
- self.check_contents(path, b'1\r\r\n2\r\n3\r4')
- path.write_text('1\r\n2\n3\r4', newline='\r')
- self.check_contents(path, b'1\r\r2\r3\r4')
+ path = self.path(self.make_path("some_file"))
+ path.write_text("1\r\n2\n3\r4", newline="")
+ self.check_contents(path, b"1\r\n2\n3\r4")
+ path.write_text("1\r\n2\n3\r4", newline="\n")
+ self.check_contents(path, b"1\r\n2\n3\r4")
+ path.write_text("1\r\n2\n3\r4", newline="\r\n")
+ self.check_contents(path, b"1\r\r\n2\r\n3\r4")
+ path.write_text("1\r\n2\n3\r4", newline="\r")
+ self.check_contents(path, b"1\r\r2\r3\r4")
def test_read_bytes(self):
- path_name = self.make_path('binary_file')
- self.create_file(path_name, contents=b'Binary file contents')
+ path_name = self.make_path("binary_file")
+ self.create_file(path_name, contents=b"Binary file contents")
file_path = self.path(path_name)
- self.assertEqual(file_path.read_bytes(), b'Binary file contents')
+ self.assertEqual(file_path.read_bytes(), b"Binary file contents")
def test_write_bytes(self):
- path_name = self.make_path('binary_file')
+ path_name = self.make_path("binary_file")
file_path = self.path(path_name)
- file_path.write_bytes(b'Binary file contents')
+ file_path.write_bytes(b"Binary file contents")
self.assertTrue(self.os.path.exists(path_name))
- self.check_contents(path_name, b'Binary file contents')
+ self.check_contents(path_name, b"Binary file contents")
def test_rename(self):
- file_name = self.make_path('foo', 'bar.txt')
- self.create_file(file_name, contents='test')
- new_file_name = self.make_path('foo', 'baz.txt')
+ file_name = self.make_path("foo", "bar.txt")
+ self.create_file(file_name, contents="test")
+ new_file_name = self.make_path("foo", "baz.txt")
self.path(file_name).rename(new_file_name)
self.assertFalse(self.os.path.exists(file_name))
- self.check_contents(new_file_name, 'test')
+ self.check_contents(new_file_name, "test")
def test_replace(self):
- self.create_file(self.make_path('foo', 'bar.txt'), contents='test')
- self.create_file(self.make_path('bar', 'old.txt'),
- contents='replaced')
- self.path(self.make_path('bar', 'old.txt')).replace(
- self.make_path('foo', 'bar.txt'))
- self.assertFalse(
- self.os.path.exists(self.make_path('bar', 'old.txt')))
- self.check_contents(self.make_path('foo', 'bar.txt'), 'replaced')
+ self.create_file(self.make_path("foo", "bar.txt"), contents="test")
+ self.create_file(self.make_path("bar", "old.txt"), contents="replaced")
+ self.path(self.make_path("bar", "old.txt")).replace(
+ self.make_path("foo", "bar.txt")
+ )
+ self.assertFalse(self.os.path.exists(self.make_path("bar", "old.txt")))
+ self.check_contents(self.make_path("foo", "bar.txt"), "replaced")
def test_unlink(self):
- file_path = self.make_path('foo', 'bar.txt')
- self.create_file(file_path, contents='test')
+ file_path = self.make_path("foo", "bar.txt")
+ self.create_file(file_path, contents="test")
self.assertTrue(self.os.path.exists(file_path))
self.path(file_path).unlink()
self.assertFalse(self.os.path.exists(file_path))
def test_touch_non_existing(self):
- self.create_dir(self.make_path('foo'))
- file_name = self.make_path('foo', 'bar.txt')
+ self.create_dir(self.make_path("foo"))
+ file_name = self.make_path("foo", "bar.txt")
self.path(file_name).touch(mode=0o444)
- self.check_contents(file_name, '')
- self.assertTrue(self.os.stat(file_name).st_mode,
- stat.S_IFREG | 0o444)
+ self.check_contents(file_name, "")
+ self.assertTrue(self.os.stat(file_name).st_mode, stat.S_IFREG | 0o444)
self.os.chmod(file_name, mode=0o666)
def test_touch_existing(self):
- file_name = self.make_path('foo', 'bar.txt')
- self.create_file(file_name, contents='test')
+ file_name = self.make_path("foo", "bar.txt")
+ self.create_file(file_name, contents="test")
file_path = self.path(file_name)
- self.assert_raises_os_error(
- errno.EEXIST, file_path.touch, exist_ok=False)
+ self.assert_raises_os_error(errno.EEXIST, file_path.touch, exist_ok=False)
file_path.touch()
- self.check_contents(file_name, 'test')
+ self.check_contents(file_name, "test")
def test_samefile(self):
- file_name = self.make_path('foo', 'bar.txt')
+ file_name = self.make_path("foo", "bar.txt")
self.create_file(file_name)
- file_name2 = self.make_path('foo', 'baz.txt')
+ file_name2 = self.make_path("foo", "baz.txt")
self.create_file(file_name2)
with self.assertRaises(OSError):
- self.path(self.make_path('foo', 'other')).samefile(
- self.make_path('foo', 'other.txt'))
+ self.path(self.make_path("foo", "other")).samefile(
+ self.make_path("foo", "other.txt")
+ )
path = self.path(file_name)
- other_name = self.make_path('foo', 'other.txt')
+ other_name = self.make_path("foo", "other.txt")
with self.assertRaises(OSError):
path.samefile(other_name)
with self.assertRaises(OSError):
path.samefile(self.path(other_name))
self.assertFalse(path.samefile(file_name2))
self.assertFalse(path.samefile(self.path(file_name2)))
+ self.assertTrue(path.samefile(self.make_path("foo", "..", "foo", "bar.txt")))
self.assertTrue(
- path.samefile(self.make_path('foo', '..', 'foo', 'bar.txt')))
- self.assertTrue(path.samefile(
- self.path(self.make_path('foo', '..', 'foo', 'bar.txt'))))
+ path.samefile(self.path(self.make_path("foo", "..", "foo", "bar.txt")))
+ )
def test_symlink_to(self):
self.skip_if_symlink_not_supported()
- file_name = self.make_path('foo', 'bar.txt')
+ file_name = self.make_path("foo", "bar.txt")
self.create_file(file_name)
- link_name = self.make_path('link_to_bar')
+ link_name = self.make_path("link_to_bar")
path = self.path(link_name)
path.symlink_to(file_name)
self.assertTrue(self.os.path.exists(link_name))
self.assertTrue(path.is_symlink())
- @unittest.skipIf(sys.version_info < (3, 8),
- 'link_to new in Python 3.8')
+ @unittest.skipIf(sys.version_info < (3, 8), "link_to new in Python 3.8")
+ @unittest.skipIf(sys.version_info >= (3, 12), "link_to removed in Python 3.12")
def test_link_to(self):
self.skip_if_symlink_not_supported()
- file_name = self.make_path('foo', 'bar.txt')
+ file_name = self.make_path("foo", "bar.txt")
self.create_file(file_name)
self.assertEqual(1, self.os.stat(file_name).st_nlink)
- link_name = self.make_path('link_to_bar')
+ link_name = self.make_path("link_to_bar")
path = self.path(file_name)
path.link_to(link_name)
self.assertTrue(self.os.path.exists(link_name))
self.assertFalse(path.is_symlink())
self.assertEqual(2, self.os.stat(file_name).st_nlink)
- @unittest.skipIf(sys.version_info < (3, 10),
- 'hardlink_to new in Python 3.10')
+ @unittest.skipIf(sys.version_info < (3, 10), "hardlink_to new in Python 3.10")
def test_hardlink_to(self):
self.skip_if_symlink_not_supported()
- file_name = self.make_path('foo', 'bar.txt')
+ file_name = self.make_path("foo", "bar.txt")
self.create_file(file_name)
self.assertEqual(1, self.os.stat(file_name).st_nlink)
- link_path = self.path(self.make_path('link_to_bar'))
+ link_path = self.path(self.make_path("link_to_bar"))
path = self.path(file_name)
link_path.hardlink_to(path)
self.assertTrue(self.os.path.exists(link_path))
self.assertFalse(path.is_symlink())
self.assertEqual(2, self.os.stat(file_name).st_nlink)
- @unittest.skipIf(sys.version_info < (3, 9),
- 'readlink new in Python 3.9')
+ @unittest.skipIf(sys.version_info < (3, 9), "readlink new in Python 3.9")
def test_readlink(self):
self.skip_if_symlink_not_supported()
- link_path = self.make_path('foo', 'bar', 'baz')
- target = self.make_path('tarJAY')
+ link_path = self.make_path("foo", "bar", "baz")
+ target = self.make_path("tarJAY")
self.create_symlink(link_path, target)
path = self.path(link_path)
self.assert_equal_paths(path.readlink(), self.path(target))
def test_mkdir(self):
- dir_name = self.make_path('foo', 'bar')
- self.assert_raises_os_error(errno.ENOENT,
- self.path(dir_name).mkdir)
+ dir_name = self.make_path("foo", "bar")
+ self.assert_raises_os_error(errno.ENOENT, self.path(dir_name).mkdir)
self.path(dir_name).mkdir(parents=True)
self.assertTrue(self.os.path.exists(dir_name))
- self.assert_raises_os_error(errno.EEXIST,
- self.path(dir_name).mkdir)
+ self.assert_raises_os_error(errno.EEXIST, self.path(dir_name).mkdir)
def test_mkdir_exist_ok(self):
- dir_name = self.make_path('foo', 'bar')
+ dir_name = self.make_path("foo", "bar")
self.create_dir(dir_name)
self.path(dir_name).mkdir(exist_ok=True)
- file_name = self.os.path.join(dir_name, 'baz')
+ file_name = self.os.path.join(dir_name, "baz")
self.create_file(file_name)
- self.assert_raises_os_error(errno.EEXIST,
- self.path(file_name).mkdir,
- exist_ok=True)
+ self.assert_raises_os_error(
+ errno.EEXIST, self.path(file_name).mkdir, exist_ok=True
+ )
def test_rmdir(self):
- dir_name = self.make_path('foo', 'bar')
+ dir_name = self.make_path("foo", "bar")
self.create_dir(dir_name)
self.path(dir_name).rmdir()
self.assertFalse(self.os.path.exists(dir_name))
- self.assertTrue(self.os.path.exists(self.make_path('foo')))
- self.create_file(self.make_path('foo', 'baz'))
+ self.assertTrue(self.os.path.exists(self.make_path("foo")))
+ self.create_file(self.make_path("foo", "baz"))
with self.assertRaises(OSError):
- self.path(self.make_path('foo')).rmdir()
- self.assertTrue(self.os.path.exists(self.make_path('foo')))
+ self.path(self.make_path("foo")).rmdir()
+ self.assertTrue(self.os.path.exists(self.make_path("foo")))
def test_iterdir(self):
- self.create_file(self.make_path('foo', 'bar', 'file1'))
- self.create_file(self.make_path('foo', 'bar', 'file2'))
- self.create_file(self.make_path('foo', 'bar', 'file3'))
- path = self.path(self.make_path('foo', 'bar'))
+ self.create_file(self.make_path("foo", "bar", "file1"))
+ self.create_file(self.make_path("foo", "bar", "file2"))
+ self.create_file(self.make_path("foo", "bar", "file3"))
+ path = self.path(self.make_path("foo", "bar"))
contents = [entry for entry in path.iterdir()]
self.assertEqual(3, len(contents))
- self.assertIn(self.path(self.make_path('foo', 'bar', 'file2')),
- contents)
+ self.assertIn(self.path(self.make_path("foo", "bar", "file2")), contents)
def test_glob(self):
- self.create_file(self.make_path('foo', 'setup.py'))
- self.create_file(self.make_path('foo', 'all_tests.py'))
- self.create_file(self.make_path('foo', 'README.md'))
- self.create_file(self.make_path('foo', 'setup.pyc'))
- path = self.path(self.make_path('foo'))
- self.assertEqual(sorted(path.glob('*.py')),
- [self.path(self.make_path('foo', 'all_tests.py')),
- self.path(self.make_path('foo', 'setup.py'))])
-
- @unittest.skipIf(not is_windows, 'Windows specific test')
+ self.create_file(self.make_path("foo", "setup.py"))
+ self.create_file(self.make_path("foo", "all_tests.py"))
+ self.create_file(self.make_path("foo", "README.md"))
+ self.create_file(self.make_path("foo", "setup.pyc"))
+ path = self.path(self.make_path("foo"))
+ self.assertEqual(
+ sorted(path.glob("*.py")),
+ [
+ self.path(self.make_path("foo", "all_tests.py")),
+ self.path(self.make_path("foo", "setup.py")),
+ ],
+ )
+
+ @unittest.skipIf(not is_windows, "Windows specific test")
def test_glob_case_windows(self):
- self.create_file(self.make_path('foo', 'setup.py'))
- self.create_file(self.make_path('foo', 'all_tests.PY'))
- self.create_file(self.make_path('foo', 'README.md'))
- self.create_file(self.make_path('foo', 'example.Py'))
- path = self.path(self.make_path('foo'))
- self.assertEqual(sorted(path.glob('*.py')),
- [self.path(self.make_path('foo', 'all_tests.PY')),
- self.path(self.make_path('foo', 'example.Py')),
- self.path(self.make_path('foo', 'setup.py'))])
-
- @unittest.skipIf(is_windows, 'Posix specific test')
+ self.create_file(self.make_path("foo", "setup.py"))
+ self.create_file(self.make_path("foo", "all_tests.PY"))
+ self.create_file(self.make_path("foo", "README.md"))
+ self.create_file(self.make_path("foo", "example.Py"))
+ path = self.path(self.make_path("foo"))
+ self.assertEqual(
+ sorted(path.glob("*.py")),
+ [
+ self.path(self.make_path("foo", "all_tests.PY")),
+ self.path(self.make_path("foo", "example.Py")),
+ self.path(self.make_path("foo", "setup.py")),
+ ],
+ )
+
+ @unittest.skipIf(is_windows, "Posix specific test")
def test_glob_case_posix(self):
self.check_posix_only()
- self.create_file(self.make_path('foo', 'setup.py'))
- self.create_file(self.make_path('foo', 'all_tests.PY'))
- self.create_file(self.make_path('foo', 'README.md'))
- self.create_file(self.make_path('foo', 'example.Py'))
- path = self.path(self.make_path('foo'))
- self.assertEqual(sorted(path.glob('*.py')),
- [self.path(self.make_path('foo', 'setup.py'))])
+ self.create_file(self.make_path("foo", "setup.py"))
+ self.create_file(self.make_path("foo", "all_tests.PY"))
+ self.create_file(self.make_path("foo", "README.md"))
+ self.create_file(self.make_path("foo", "example.Py"))
+ path = self.path(self.make_path("foo"))
+ self.assertEqual(
+ sorted(path.glob("*.py")),
+ [self.path(self.make_path("foo", "setup.py"))],
+ )
class RealPathlibPathFileOperationTest(FakePathlibPathFileOperationTest):
@@ -758,8 +771,6 @@ class RealPathlibPathFileOperationTest(FakePathlibPathFileOperationTest):
return True
-@unittest.skipIf(sys.version_info < (3, 6),
- 'path-like objects new in Python 3.6')
class FakePathlibUsageInOsFunctionsTest(RealPathlibTestCase):
"""Test that many os / os.path functions accept a path-like object
since Python 3.6. The functionality of these functions is tested
@@ -768,163 +779,174 @@ class FakePathlibUsageInOsFunctionsTest(RealPathlibTestCase):
"""
def test_join(self):
- dir1 = 'foo'
- dir2 = 'bar'
+ dir1 = "foo"
+ dir2 = "bar"
dir = self.os.path.join(dir1, dir2)
self.assertEqual(dir, self.os.path.join(self.path(dir1), dir2))
self.assertEqual(dir, self.os.path.join(dir1, self.path(dir2)))
- self.assertEqual(dir,
- self.os.path.join(self.path(dir1),
- self.path(dir2)))
+ self.assertEqual(dir, self.os.path.join(self.path(dir1), self.path(dir2)))
def test_normcase(self):
- dir1 = self.make_path('Foo', 'Bar', 'Baz')
- self.assertEqual(self.os.path.normcase(dir1),
- self.os.path.normcase(self.path(dir1)))
+ dir1 = self.make_path("Foo", "Bar", "Baz")
+ self.assertEqual(
+ self.os.path.normcase(dir1), self.os.path.normcase(self.path(dir1))
+ )
def test_normpath(self):
- dir1 = self.make_path('foo', 'bar', '..', 'baz')
- self.assertEqual(self.os.path.normpath(dir1),
- self.os.path.normpath(self.path(dir1)))
+ dir1 = self.make_path("foo", "bar", "..", "baz")
+ self.assertEqual(
+ self.os.path.normpath(dir1), self.os.path.normpath(self.path(dir1))
+ )
def test_realpath(self):
- dir1 = self.make_path('foo', 'bar', '..', 'baz')
- self.assertEqual(self.os.path.realpath(dir1),
- self.os.path.realpath(self.path(dir1)))
+ dir1 = self.make_path("foo", "bar", "..", "baz")
+ self.assertEqual(
+ self.os.path.realpath(dir1), self.os.path.realpath(self.path(dir1))
+ )
def test_relpath(self):
- path_foo = self.make_path('path', 'to', 'foo')
- path_bar = self.make_path('path', 'to', 'bar')
+ path_foo = self.make_path("path", "to", "foo")
+ path_bar = self.make_path("path", "to", "bar")
rel_path = self.os.path.relpath(path_foo, path_bar)
- self.assertEqual(rel_path,
- self.os.path.relpath(self.path(path_foo),
- path_bar))
- self.assertEqual(rel_path,
- self.os.path.relpath(path_foo,
- self.path(path_bar)))
- self.assertEqual(rel_path,
- self.os.path.relpath(self.path(path_foo),
- self.path(path_bar)))
+ self.assertEqual(rel_path, self.os.path.relpath(self.path(path_foo), path_bar))
+ self.assertEqual(rel_path, self.os.path.relpath(path_foo, self.path(path_bar)))
+ self.assertEqual(
+ rel_path,
+ self.os.path.relpath(self.path(path_foo), self.path(path_bar)),
+ )
def test_split(self):
- dir1 = self.make_path('Foo', 'Bar', 'Baz')
- self.assertEqual(self.os.path.split(dir1),
- self.os.path.split(self.path(dir1)))
+ dir1 = self.make_path("Foo", "Bar", "Baz")
+ self.assertEqual(self.os.path.split(dir1), self.os.path.split(self.path(dir1)))
def test_splitdrive(self):
- dir1 = self.make_path('C:', 'Foo', 'Bar', 'Baz')
- self.assertEqual(self.os.path.splitdrive(dir1),
- self.os.path.splitdrive(self.path(dir1)))
+ dir1 = self.make_path("C:", "Foo", "Bar", "Baz")
+ self.assertEqual(
+ self.os.path.splitdrive(dir1),
+ self.os.path.splitdrive(self.path(dir1)),
+ )
def test_abspath(self):
- dir1 = self.make_path('foo', 'bar', '..', 'baz')
- self.assertEqual(self.os.path.abspath(dir1),
- self.os.path.abspath(self.path(dir1)))
+ dir1 = self.make_path("foo", "bar", "..", "baz")
+ self.assertEqual(
+ self.os.path.abspath(dir1), self.os.path.abspath(self.path(dir1))
+ )
def test_exists(self):
- dir1 = self.make_path('foo', 'bar', '..', 'baz')
- self.assertEqual(self.os.path.exists(dir1),
- self.os.path.exists(self.path(dir1)))
+ dir1 = self.make_path("foo", "bar", "..", "baz")
+ self.assertEqual(
+ self.os.path.exists(dir1), self.os.path.exists(self.path(dir1))
+ )
def test_lexists(self):
- dir1 = self.make_path('foo', 'bar', '..', 'baz')
- self.assertEqual(self.os.path.lexists(dir1),
- self.os.path.lexists(self.path(dir1)))
+ dir1 = self.make_path("foo", "bar", "..", "baz")
+ self.assertEqual(
+ self.os.path.lexists(dir1), self.os.path.lexists(self.path(dir1))
+ )
def test_expanduser(self):
- dir1 = self.os.path.join('~', 'foo')
- self.assertEqual(self.os.path.expanduser(dir1),
- self.os.path.expanduser(self.path(dir1)))
+ dir1 = self.os.path.join("~", "foo")
+ self.assertEqual(
+ self.os.path.expanduser(dir1),
+ self.os.path.expanduser(self.path(dir1)),
+ )
def test_getmtime(self):
self.skip_real_fs()
- dir1 = self.make_path('foo', 'bar1.txt')
+ dir1 = self.make_path("foo", "bar1.txt")
path_obj = self.filesystem.create_file(dir1)
path_obj._st_mtime = 24
- self.assertEqual(self.os.path.getmtime(dir1),
- self.os.path.getmtime(self.path(dir1)))
+ self.assertEqual(
+ self.os.path.getmtime(dir1), self.os.path.getmtime(self.path(dir1))
+ )
def test_getctime(self):
self.skip_real_fs()
- dir1 = self.make_path('foo', 'bar1.txt')
+ dir1 = self.make_path("foo", "bar1.txt")
path_obj = self.filesystem.create_file(dir1)
path_obj.st_ctime = 42
- self.assertEqual(self.os.path.getctime(dir1),
- self.os.path.getctime(self.path(dir1)))
+ self.assertEqual(
+ self.os.path.getctime(dir1), self.os.path.getctime(self.path(dir1))
+ )
def test_getatime(self):
self.skip_real_fs()
- dir1 = self.make_path('foo', 'bar1.txt')
+ dir1 = self.make_path("foo", "bar1.txt")
path_obj = self.filesystem.create_file(dir1)
path_obj.st_atime = 11
- self.assertEqual(self.os.path.getatime(dir1),
- self.os.path.getatime(self.path(dir1)))
+ self.assertEqual(
+ self.os.path.getatime(dir1), self.os.path.getatime(self.path(dir1))
+ )
def test_getsize(self):
- path = self.make_path('foo', 'bar', 'baz')
- self.create_file(path, contents='1234567')
- self.assertEqual(self.os.path.getsize(path),
- self.os.path.getsize(self.path(path)))
+ path = self.make_path("foo", "bar", "baz")
+ self.create_file(path, contents="1234567")
+ self.assertEqual(
+ self.os.path.getsize(path), self.os.path.getsize(self.path(path))
+ )
def test_isabs(self):
- path = self.make_path('foo', 'bar', '..', 'baz')
- self.assertEqual(self.os.path.isabs(path),
- self.os.path.isabs(self.path(path)))
+ path = self.make_path("foo", "bar", "..", "baz")
+ self.assertEqual(self.os.path.isabs(path), self.os.path.isabs(self.path(path)))
def test_isfile(self):
- path = self.make_path('foo', 'bar', 'baz')
+ path = self.make_path("foo", "bar", "baz")
self.create_file(path)
- self.assertEqual(self.os.path.isfile(path),
- self.os.path.isfile(self.path(path)))
+ self.assertEqual(
+ self.os.path.isfile(path), self.os.path.isfile(self.path(path))
+ )
def test_isfile_not_readable(self):
- path = self.make_path('foo', 'bar', 'baz')
+ path = self.make_path("foo", "bar", "baz")
self.create_file(path, perm=0)
- self.assertEqual(self.os.path.isfile(path),
- self.os.path.isfile(self.path(path)))
+ self.assertEqual(
+ self.os.path.isfile(path), self.os.path.isfile(self.path(path))
+ )
def test_islink(self):
- path = self.make_path('foo', 'bar', 'baz')
+ path = self.make_path("foo", "bar", "baz")
self.create_file(path)
- self.assertEqual(self.os.path.islink(path),
- self.os.path.islink(self.path(path)))
+ self.assertEqual(
+ self.os.path.islink(path), self.os.path.islink(self.path(path))
+ )
def test_isdir(self):
- path = self.make_path('foo', 'bar', 'baz')
+ path = self.make_path("foo", "bar", "baz")
self.create_file(path)
- self.assertEqual(self.os.path.isdir(path),
- self.os.path.isdir(self.path(path)))
+ self.assertEqual(self.os.path.isdir(path), self.os.path.isdir(self.path(path)))
def test_ismount(self):
path = self.os.path.sep
- self.assertEqual(self.os.path.ismount(path),
- self.os.path.ismount(self.path(path)))
+ self.assertEqual(
+ self.os.path.ismount(path), self.os.path.ismount(self.path(path))
+ )
def test_access(self):
- path = self.make_path('foo', 'bar', 'baz')
- self.create_file(path, contents='1234567')
- self.assertEqual(self.os.access(path, os.R_OK),
- self.os.access(self.path(path), os.R_OK))
+ path = self.make_path("foo", "bar", "baz")
+ self.create_file(path, contents="1234567")
+ self.assertEqual(
+ self.os.access(path, os.R_OK),
+ self.os.access(self.path(path), os.R_OK),
+ )
def test_chdir(self):
- path = self.make_path('foo', 'bar', 'baz')
+ path = self.make_path("foo", "bar", "baz")
self.create_dir(path)
self.os.chdir(self.path(path))
# use real path to handle symlink /var to /private/var in MacOs
self.assert_equal_paths(self.os.path.realpath(path), self.os.getcwd())
def test_chmod(self):
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.create_file(path)
self.os.chmod(self.path(path), 0o444)
- self.assertEqual(stat.S_IMODE(0o444),
- stat.S_IMODE(self.os.stat(path).st_mode))
+ self.assertEqual(stat.S_IMODE(0o444), stat.S_IMODE(self.os.stat(path).st_mode))
self.os.chmod(self.path(path), 0o666)
def test_link(self):
self.skip_if_symlink_not_supported()
- file1_path = self.make_path('test_file1')
- file2_path = self.make_path('test_file2')
+ file1_path = self.make_path("test_file1")
+ file2_path = self.make_path("test_file2")
self.create_file(file1_path)
self.os.link(self.path(file1_path), file2_path)
self.assertTrue(self.os.path.exists(file2_path))
@@ -936,51 +958,54 @@ class FakePathlibUsageInOsFunctionsTest(RealPathlibTestCase):
self.assertTrue(self.os.path.exists(file2_path))
def test_listdir(self):
- path = self.make_path('foo', 'bar')
+ path = self.make_path("foo", "bar")
self.create_dir(path)
- self.create_file(path + 'baz.txt')
- self.assertEqual(self.os.listdir(path),
- self.os.listdir(self.path(path)))
+ self.create_file(path + "baz.txt")
+ self.assertEqual(self.os.listdir(path), self.os.listdir(self.path(path)))
def test_mkdir(self):
- path = self.make_path('foo')
+ path = self.make_path("foo")
self.os.mkdir(self.path(path))
self.assertTrue(self.os.path.exists(path))
def test_makedirs(self):
- path = self.make_path('foo', 'bar')
+ path = self.make_path("foo", "bar")
self.os.makedirs(self.path(path))
self.assertTrue(self.os.path.exists(path))
- @unittest.skipIf(is_windows and sys.version_info < (3, 8),
- 'os.readlink does not to support path-like objects '
- 'under Windows before Python 3.8')
+ @unittest.skipIf(
+ is_windows and sys.version_info < (3, 8),
+ "os.readlink does not to support path-like objects "
+ "under Windows before Python 3.8",
+ )
def test_readlink(self):
self.skip_if_symlink_not_supported()
- link_path = self.make_path('foo', 'bar', 'baz')
- target = self.make_path('tarJAY')
+ link_path = self.make_path("foo", "bar", "baz")
+ target = self.make_path("tarJAY")
self.create_symlink(link_path, target)
self.assert_equal_paths(self.os.readlink(self.path(link_path)), target)
- @unittest.skipIf(is_windows and sys.version_info < (3, 8),
- 'os.readlink does not to support path-like objects '
- 'under Windows before Python 3.8')
+ @unittest.skipIf(
+ is_windows and sys.version_info < (3, 8),
+ "os.readlink does not to support path-like objects "
+ "under Windows before Python 3.8",
+ )
def test_readlink_bytes(self):
self.skip_if_symlink_not_supported()
- link_path = self.make_path(b'foo', b'bar', b'baz')
- target = self.make_path(b'tarJAY')
+ link_path = self.make_path(b"foo", b"bar", b"baz")
+ target = self.make_path(b"tarJAY")
self.create_symlink(link_path, target)
self.assert_equal_paths(self.os.readlink(self.path(link_path)), target)
def test_remove(self):
- path = self.make_path('test.txt')
+ path = self.make_path("test.txt")
self.create_file(path)
self.os.remove(self.path(path))
self.assertFalse(self.os.path.exists(path))
def test_rename(self):
- path1 = self.make_path('test1.txt')
- path2 = self.make_path('test2.txt')
+ path1 = self.make_path("test1.txt")
+ path2 = self.make_path("test2.txt")
self.create_file(path1)
self.os.rename(self.path(path1), path2)
self.assertTrue(self.os.path.exists(path2))
@@ -988,8 +1013,8 @@ class FakePathlibUsageInOsFunctionsTest(RealPathlibTestCase):
self.assertTrue(self.os.path.exists(path1))
def test_replace(self):
- path1 = self.make_path('test1.txt')
- path2 = self.make_path('test2.txt')
+ path1 = self.make_path("test1.txt")
+ path2 = self.make_path("test2.txt")
self.create_file(path1)
self.os.replace(self.path(path1), path2)
self.assertTrue(self.os.path.exists(path2))
@@ -997,23 +1022,22 @@ class FakePathlibUsageInOsFunctionsTest(RealPathlibTestCase):
self.assertTrue(self.os.path.exists(path1))
def test_rmdir(self):
- path = self.make_path('foo', 'bar')
+ path = self.make_path("foo", "bar")
self.create_dir(path)
self.os.rmdir(self.path(path))
self.assertFalse(self.os.path.exists(path))
def test_scandir(self):
- directory = self.make_path('xyzzy', 'plugh')
+ directory = self.make_path("xyzzy", "plugh")
self.create_dir(directory)
- self.create_file(self.os.path.join(directory, 'test.txt'))
- dir_entries = [entry for entry in
- self.os.scandir(self.path(directory))]
+ self.create_file(self.os.path.join(directory, "test.txt"))
+ dir_entries = [entry for entry in self.os.scandir(self.path(directory))]
self.assertEqual(1, len(dir_entries))
def test_symlink(self):
self.skip_if_symlink_not_supported()
- file_path = self.make_path('test_file1')
- link_path = self.make_path('link')
+ file_path = self.make_path("test_file1")
+ link_path = self.make_path("link")
self.create_file(file_path)
self.os.symlink(self.path(file_path), link_path)
self.assertTrue(self.os.path.exists(link_path))
@@ -1022,52 +1046,77 @@ class FakePathlibUsageInOsFunctionsTest(RealPathlibTestCase):
self.assertTrue(self.os.path.exists(link_path))
def test_stat(self):
- path = self.make_path('foo', 'bar', 'baz')
- self.create_file(path, contents='1234567')
+ path = self.make_path("foo", "bar", "baz")
+ self.create_file(path, contents="1234567")
self.assertEqual(self.os.stat(path), self.path(path).stat())
@unittest.skipIf(sys.version_info < (3, 10), "New in Python 3.10")
def test_stat_follow_symlinks(self):
self.check_posix_only()
- directory = self.make_path('foo')
- base_name = 'bar'
+ directory = self.make_path("foo")
+ base_name = "bar"
file_path = self.path(self.os.path.join(directory, base_name))
- link_path = self.path(self.os.path.join(directory, 'link'))
+ link_path = self.path(self.os.path.join(directory, "link"))
contents = "contents"
self.create_file(file_path, contents=contents)
self.create_symlink(link_path, base_name)
- self.assertEqual(len(contents),
- link_path.stat(follow_symlinks=True)[stat.ST_SIZE])
- self.assertEqual(len(base_name),
- link_path.stat(follow_symlinks=False)[stat.ST_SIZE])
+ self.assertEqual(
+ len(contents), link_path.stat(follow_symlinks=True)[stat.ST_SIZE]
+ )
+ self.assertEqual(
+ len(base_name), link_path.stat(follow_symlinks=False)[stat.ST_SIZE]
+ )
def test_utime(self):
- path = self.make_path('some_file')
- self.create_file(path, contents='test')
+ path = self.make_path("some_file")
+ self.create_file(path, contents="test")
self.os.utime(self.path(path), times=(1, 2))
st = self.os.stat(path)
self.assertEqual(1, st.st_atime)
self.assertEqual(2, st.st_mtime)
def test_truncate(self):
- path = self.make_path('some_file')
- self.create_file(path, contents='test_test')
+ path = self.make_path("some_file")
+ self.create_file(path, contents="test_test")
self.os.truncate(self.path(path), length=4)
st = self.os.stat(path)
self.assertEqual(4, st.st_size)
- @unittest.skipIf(sys.platform == 'win32',
- 'no pwd and grp modules in Windows')
+ @unittest.skipIf(sys.platform == "win32", "no pwd and grp modules in Windows")
def test_owner_and_group_posix(self):
- self.check_posix_only()
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.create_file(path)
self.assertTrue(self.path(path).owner())
self.assertTrue(self.path(path).group())
+ @unittest.skipIf(sys.platform == "win32", "no pwd and grp modules in Windows")
+ def test_changed_owner_and_group(self):
+ def fake_getpwuid(uid):
+ if uid == 42:
+ user_struct = namedtuple("user", "pw_name, pw_uid")
+ user_struct.pw_name = "NewUser"
+ return user_struct
+ raise KeyError
+
+ def fake_getgrgid(uid):
+ if uid == 5:
+ group_struct = namedtuple("group", "gr_name, gr_gid")
+ group_struct.gr_name = "NewGroup"
+ return group_struct
+ raise KeyError
+
+ self.skip_real_fs()
+ path = self.make_path("some_file")
+ self.create_file(path)
+ self.os.chown(path, 42, 5)
+ with mock.patch("pwd.getpwuid", fake_getpwuid):
+ with mock.patch("grp.getgrgid", fake_getgrgid):
+ self.assertEqual("NewUser", self.path(path).owner())
+ self.assertEqual("NewGroup", self.path(path).group())
+
def test_owner_and_group_windows(self):
self.check_windows_only()
- path = self.make_path('some_file')
+ path = self.make_path("some_file")
self.create_file(path)
with self.assertRaises(NotImplementedError):
self.path(path).owner()
@@ -1080,64 +1129,81 @@ class RealPathlibUsageInOsFunctionsTest(FakePathlibUsageInOsFunctionsTest):
return True
-@unittest.skipIf(sys.version_info < (3, 6),
- 'Path-like objects new in Python 3.6')
class FakeFilesystemPathLikeObjectTest(unittest.TestCase):
-
def setUp(self):
- self.filesystem = fake_filesystem.FakeFilesystem(
- path_separator='/')
+ self.filesystem = fake_filesystem.FakeFilesystem(path_separator="/")
self.pathlib = fake_pathlib.FakePathlibModule(self.filesystem)
- self.os = fake_filesystem.FakeOsModule(self.filesystem)
+ self.os = fake_os.FakeOsModule(self.filesystem)
def test_create_dir_with_pathlib_path(self):
- dir_path_string = 'foo/bar/baz'
+ dir_path_string = "foo/bar/baz"
dir_path = self.pathlib.Path(dir_path_string)
self.filesystem.create_dir(dir_path)
self.assertTrue(self.os.path.exists(dir_path_string))
- self.assertEqual(stat.S_IFDIR,
- self.os.stat(
- dir_path_string).st_mode & stat.S_IFDIR)
+ self.assertEqual(
+ stat.S_IFDIR, self.os.stat(dir_path_string).st_mode & stat.S_IFDIR
+ )
def test_create_file_with_pathlib_path(self):
- file_path_string = 'foo/bar/baz'
+ file_path_string = "foo/bar/baz"
file_path = self.pathlib.Path(file_path_string)
self.filesystem.create_file(file_path)
self.assertTrue(self.os.path.exists(file_path_string))
- self.assertEqual(stat.S_IFREG,
- self.os.stat(
- file_path_string).st_mode & stat.S_IFREG)
+ self.assertEqual(
+ stat.S_IFREG, self.os.stat(file_path_string).st_mode & stat.S_IFREG
+ )
def test_create_symlink_with_pathlib_path(self):
- file_path = self.pathlib.Path('foo/bar/baz')
- link_path_string = 'foo/link'
+ file_path = self.pathlib.Path("foo/bar/baz")
+ link_path_string = "foo/link"
link_path = self.pathlib.Path(link_path_string)
self.filesystem.create_symlink(link_path, file_path)
self.assertTrue(self.os.path.lexists(link_path_string))
- self.assertEqual(stat.S_IFLNK,
- self.os.lstat(link_path_string).st_mode &
- stat.S_IFLNK)
+ self.assertEqual(
+ stat.S_IFLNK,
+ self.os.lstat(link_path_string).st_mode & stat.S_IFLNK,
+ )
def test_add_existing_real_file_with_pathlib_path(self):
real_file_path_string = os.path.abspath(__file__)
real_file_path = self.pathlib.Path(real_file_path_string)
self.filesystem.add_real_file(real_file_path)
- fake_filepath_string = real_file_path_string.replace(
- os.sep, self.os.sep)
+ fake_filepath_string = real_file_path_string.replace(os.sep, self.os.sep)
self.assertTrue(self.os.path.exists(fake_filepath_string))
- self.assertEqual(stat.S_IFREG, self.os.stat(
- fake_filepath_string).st_mode & stat.S_IFREG)
+ self.assertEqual(
+ stat.S_IFREG,
+ self.os.stat(fake_filepath_string).st_mode & stat.S_IFREG,
+ )
def test_add_existing_real_directory_with_pathlib_path(self):
real_dirpath_string = os.path.dirname(os.path.abspath(__file__))
real_dir_path = self.pathlib.Path(real_dirpath_string)
self.filesystem.add_real_directory(real_dir_path)
- fake_dirpath_string = real_dirpath_string.replace(
- os.sep, self.os.sep)
+ fake_dirpath_string = real_dirpath_string.replace(os.sep, self.os.sep)
self.assertTrue(self.os.path.exists(fake_dirpath_string))
- self.assertEqual(stat.S_IFDIR, self.os.stat(
- fake_dirpath_string).st_mode & stat.S_IFDIR)
-
-
-if __name__ == '__main__':
+ self.assertEqual(
+ stat.S_IFDIR,
+ self.os.stat(fake_dirpath_string).st_mode & stat.S_IFDIR,
+ )
+
+
+class FakeFilesystemChmodTest(fake_filesystem_unittest.TestCase):
+ def setUp(self) -> None:
+ self.setUpPyfakefs()
+
+ @unittest.skipIf(sys.platform != "win32", "Windows specific test")
+ def test_is_file_for_unreadable_dir_windows(self):
+ self.fs.os = OSType.WINDOWS
+ path = pathlib.Path("/foo/bar")
+ self.fs.create_file(path)
+ # normal chmod does not really set the mode to 0
+ self.fs.chmod("/foo", 0o000)
+ self.assertTrue(path.is_file())
+ # but it does in forced UNIX mode
+ self.fs.chmod("/foo", 0o000, force_unix_mode=True)
+ with self.assertRaises(PermissionError):
+ path.is_file()
+
+
+if __name__ == "__main__":
unittest.main(verbosity=2)
diff --git a/pyfakefs/tests/fake_stat_time_test.py b/pyfakefs/tests/fake_stat_time_test.py
index 866a1a1..5833ebd 100644
--- a/pyfakefs/tests/fake_stat_time_test.py
+++ b/pyfakefs/tests/fake_stat_time_test.py
@@ -17,21 +17,20 @@ from collections import namedtuple
from pyfakefs.tests.test_utils import RealFsTestCase
-FileTime = namedtuple('FileTime', 'st_ctime, st_atime, st_mtime')
+FileTime = namedtuple("FileTime", "st_ctime, st_atime, st_mtime")
class FakeStatTestBase(RealFsTestCase):
-
def setUp(self):
super().setUp()
# we disable the tests for MacOS to avoid very long builds due
# to the 1s time resolution - we know that the functionality is
# similar to Linux
self.check_linux_and_windows()
- self.file_path = self.make_path('some_file')
+ self.file_path = self.make_path("some_file")
# MacOS has a timestamp resolution of 1 second
self.sleep_time = 1.1 if self.is_macos else 0.01
- self.mode = ''
+ self.mode = ""
def stat_time(self, path):
stat = self.os.stat(path)
@@ -41,9 +40,11 @@ class FakeStatTestBase(RealFsTestCase):
else:
# calling time.time() advances mocked time
time.time()
- return FileTime(st_ctime=stat.st_ctime,
- st_atime=stat.st_atime,
- st_mtime=stat.st_mtime)
+ return FileTime(
+ st_ctime=stat.st_ctime,
+ st_atime=stat.st_atime,
+ st_mtime=stat.st_mtime,
+ )
def assertLessExceptWindows(self, time1, time2):
if self.is_windows_fs:
@@ -68,7 +69,7 @@ class FakeStatTestBase(RealFsTestCase):
with self.mock_time():
with self.open(self.file_path, self.mode) as f:
created = self.stat_time(self.file_path)
- f.write('foo')
+ f.write("foo")
written = self.stat_time(self.file_path)
closed = self.stat_time(self.file_path)
@@ -92,7 +93,7 @@ class FakeStatTestBase(RealFsTestCase):
before = self.stat_time(self.file_path)
with self.open(self.file_path, self.mode) as f:
opened = self.stat_time(self.file_path)
- f.write('foo')
+ f.write("foo")
written = self.stat_time(self.file_path)
closed = self.stat_time(self.file_path)
@@ -118,7 +119,7 @@ class FakeStatTestBase(RealFsTestCase):
before = self.stat_time(self.file_path)
with self.open(self.file_path, self.mode) as f:
opened = self.stat_time(self.file_path)
- f.write('foo')
+ f.write("foo")
written = self.stat_time(self.file_path)
f.flush()
flushed = self.stat_time(self.file_path)
@@ -131,7 +132,7 @@ class FakeStatTestBase(RealFsTestCase):
self.create_file(self.file_path)
before = self.stat_time(self.file_path)
- with self.open(self.file_path, 'r') as f:
+ with self.open(self.file_path, "r") as f:
opened = self.stat_time(self.file_path)
f.read()
read = self.stat_time(self.file_path)
@@ -388,7 +389,7 @@ class FakeStatTestBase(RealFsTestCase):
class TestFakeModeW(FakeStatTestBase):
def setUp(self):
super(TestFakeModeW, self).setUp()
- self.mode = 'w'
+ self.mode = "w"
def test_open_close_new_file(self):
self.check_open_close_new_file()
@@ -409,7 +410,7 @@ class TestFakeModeW(FakeStatTestBase):
self.check_open_write_flush_close_w_mode()
def test_read_raises(self):
- with self.open(self.file_path, 'w') as f:
+ with self.open(self.file_path, "w") as f:
with self.assertRaises(OSError):
f.read()
@@ -422,7 +423,7 @@ class TestRealModeW(TestFakeModeW):
class TestFakeModeWPlus(FakeStatTestBase):
def setUp(self):
super(TestFakeModeWPlus, self).setUp()
- self.mode = 'w+'
+ self.mode = "w+"
def test_open_close_new_file(self):
self.check_open_close_new_file()
@@ -475,7 +476,7 @@ class TestRealModeWPlus(TestFakeModeWPlus):
class TestFakeModeA(FakeStatTestBase):
def setUp(self):
super(TestFakeModeA, self).setUp()
- self.mode = 'a'
+ self.mode = "a"
def test_open_close_new_file(self):
self.check_open_close_new_file()
@@ -496,7 +497,7 @@ class TestFakeModeA(FakeStatTestBase):
self.check_open_write_flush_close_non_w_mode()
def test_read_raises(self):
- with self.open(self.file_path, 'a') as f:
+ with self.open(self.file_path, "a") as f:
with self.assertRaises(OSError):
f.read()
@@ -509,7 +510,7 @@ class TestRealModeA(TestFakeModeA):
class TestFakeModeAPlus(FakeStatTestBase):
def setUp(self):
super(TestFakeModeAPlus, self).setUp()
- self.mode = 'a+'
+ self.mode = "a+"
def test_open_close_new_file(self):
self.check_open_close_new_file()
@@ -544,7 +545,7 @@ class TestRealModeAPlus(TestFakeModeAPlus):
class TestFakeModeR(FakeStatTestBase):
def setUp(self):
super(TestFakeModeR, self).setUp()
- self.mode = 'r'
+ self.mode = "r"
def test_open_close(self):
self.check_open_close_non_w_mode()
@@ -579,7 +580,7 @@ class TestFakeModeR(FakeStatTestBase):
def test_open_not_existing_raises(self):
with self.assertRaises(OSError):
- with self.open(self.file_path, 'r'):
+ with self.open(self.file_path, "r"):
pass
@@ -591,7 +592,7 @@ class TestRealModeR(TestFakeModeR):
class TestFakeModeRPlus(FakeStatTestBase):
def setUp(self):
super(TestFakeModeRPlus, self).setUp()
- self.mode = 'r+'
+ self.mode = "r+"
def test_open_close(self):
self.check_open_close_non_w_mode()
@@ -610,7 +611,7 @@ class TestFakeModeRPlus(FakeStatTestBase):
def test_open_not_existing_raises(self):
with self.assertRaises(OSError):
- with self.open(self.file_path, 'r+'):
+ with self.open(self.file_path, "r+"):
pass
@@ -619,5 +620,5 @@ class TestRealModeRPlus(TestFakeModeRPlus):
return True
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
diff --git a/pyfakefs/tests/fake_tempfile_test.py b/pyfakefs/tests/fake_tempfile_test.py
index 7ddd4e1..f208b56 100644
--- a/pyfakefs/tests/fake_tempfile_test.py
+++ b/pyfakefs/tests/fake_tempfile_test.py
@@ -39,79 +39,76 @@ class FakeTempfileModuleTest(fake_filesystem_unittest.TestCase):
def test_named_temporary_file_no_delete(self):
obj = tempfile.NamedTemporaryFile(delete=False)
- obj.write(b'foo')
+ obj.write(b"foo")
obj.close()
file_obj = self.fs.get_object(obj.name)
contents = file_obj.contents
- self.assertEqual('foo', contents)
- obj = tempfile.NamedTemporaryFile(mode='w', delete=False)
- obj.write('foo')
+ self.assertEqual("foo", contents)
+ obj = tempfile.NamedTemporaryFile(mode="w", delete=False)
+ obj.write("foo")
obj.close()
file_obj = self.fs.get_object(obj.name)
- self.assertEqual('foo', file_obj.contents)
+ self.assertEqual("foo", file_obj.contents)
def test_mkstemp(self):
next_fd = len(self.fs.open_files)
temporary = tempfile.mkstemp()
self.assertEqual(2, len(temporary))
self.assertTrue(
- temporary[1].startswith(
- os.path.join(tempfile.gettempdir(), 'tmp')))
+ temporary[1].startswith(os.path.join(tempfile.gettempdir(), "tmp"))
+ )
self.assertEqual(next_fd, temporary[0])
self.assertTrue(self.fs.exists(temporary[1]))
mode = 0o666 if self.fs.is_windows_fs else 0o600
- self.assertEqual(self.fs.get_object(temporary[1]).st_mode,
- stat.S_IFREG | mode)
- fh = os.fdopen(temporary[0], 'w+b')
+ self.assertEqual(self.fs.get_object(temporary[1]).st_mode, stat.S_IFREG | mode)
+ fh = os.fdopen(temporary[0], "w+b")
self.assertEqual(temporary[0], fh.fileno())
def test_mkstemp_dir(self):
"""test tempfile.mkstemp(dir=)."""
# expect fail: /dir does not exist
with self.assertRaises(OSError):
- tempfile.mkstemp(dir='/dir')
+ tempfile.mkstemp(dir="/dir")
# expect pass: /dir exists
- self.fs.create_dir('/dir')
+ self.fs.create_dir("/dir")
next_fd = len(self.fs.open_files)
- temporary = tempfile.mkstemp(dir='/dir')
+ temporary = tempfile.mkstemp(dir="/dir")
self.assertEqual(2, len(temporary))
self.assertEqual(next_fd, temporary[0])
- self.assertTrue(temporary[1].startswith(
- os.path.join(os.sep, 'dir', 'tmp')))
+ self.assertTrue(
+ temporary[1].startswith(os.path.join(self.fs.root_dir_name, "dir", "tmp"))
+ )
self.assertTrue(self.fs.exists(temporary[1]))
mode = 0o666 if self.fs.is_windows_fs else 0o600
- self.assertEqual(self.fs.get_object(temporary[1]).st_mode,
- stat.S_IFREG | mode)
+ self.assertEqual(self.fs.get_object(temporary[1]).st_mode, stat.S_IFREG | mode)
def test_mkdtemp(self):
dirname = tempfile.mkdtemp()
self.assertTrue(dirname)
self.assertTrue(self.fs.exists(dirname))
- self.assertEqual(self.fs.get_object(dirname).st_mode,
- stat.S_IFDIR | 0o700)
+ self.assertEqual(self.fs.get_object(dirname).st_mode, stat.S_IFDIR | 0o700)
def test_temporary_directory(self):
with tempfile.TemporaryDirectory() as tmpdir:
self.assertTrue(tmpdir)
self.assertTrue(self.fs.exists(tmpdir))
- self.assertEqual(self.fs.get_object(tmpdir).st_mode,
- stat.S_IFDIR | 0o700)
+ self.assertEqual(self.fs.get_object(tmpdir).st_mode, stat.S_IFDIR | 0o700)
def test_temporary_file(self):
with tempfile.TemporaryFile() as f:
- f.write(b'test')
+ f.write(b"test")
f.seek(0)
- self.assertEqual(b'test', f.read())
+ self.assertEqual(b"test", f.read())
def test_temporay_file_with_dir(self):
with self.assertRaises(FileNotFoundError):
- tempfile.TemporaryFile(dir='/parent')
- os.mkdir('/parent')
+ tempfile.TemporaryFile(dir="/parent")
+ os.mkdir("/parent")
with tempfile.TemporaryFile() as f:
- f.write(b'test')
+ f.write(b"test")
f.seek(0)
- self.assertEqual(b'test', f.read())
+ self.assertEqual(b"test", f.read())
-if __name__ == '__main__':
+if __name__ == "__main__":
unittest.main()
diff --git a/pyfakefs/tests/fixtures/config_module.py b/pyfakefs/tests/fixtures/config_module.py
index d384c67..0cdb2e1 100644
--- a/pyfakefs/tests/fixtures/config_module.py
+++ b/pyfakefs/tests/fixtures/config_module.py
@@ -1 +1 @@
-configurable_value = 'another value'
+configurable_value = "another value"
diff --git a/pyfakefs/tests/fixtures/deprecated_property.py b/pyfakefs/tests/fixtures/deprecated_property.py
index 1c04119..9bdb590 100644
--- a/pyfakefs/tests/fixtures/deprecated_property.py
+++ b/pyfakefs/tests/fixtures/deprecated_property.py
@@ -18,12 +18,11 @@ import warnings
class DeprecatedProperty:
-
def __get__(self, instance, cls):
- warnings.warn("async is deprecated", DeprecationWarning)
- warnings.warn("async will be replaced", FutureWarning)
+ warnings.warn("async is deprecated", DeprecationWarning, stacklevel=2)
+ warnings.warn("async will be replaced", FutureWarning, stacklevel=2)
return instance
class DeprecationTest:
- locals()['async'] = DeprecatedProperty()
+ locals()["async"] = DeprecatedProperty()
diff --git a/pyfakefs/tests/fixtures/module_with_attributes.py b/pyfakefs/tests/fixtures/module_with_attributes.py
index 02c5694..134cf14 100644
--- a/pyfakefs/tests/fixtures/module_with_attributes.py
+++ b/pyfakefs/tests/fixtures/module_with_attributes.py
@@ -23,8 +23,8 @@ attribute should be added here and in the test
:py:class:`fake_filesystem_unittest_test.TestAttributesWithFakeModuleNames`.
"""
-os = 'os attribute value'
-path = 'path attribute value'
-pathlib = 'pathlib attribute value'
-shutil = 'shutil attribute value'
-io = 'io attribute value'
+os = "os attribute value"
+path = "path attribute value"
+pathlib = "pathlib attribute value"
+shutil = "shutil attribute value"
+io = "io attribute value"
diff --git a/pyfakefs/tests/import_as_example.py b/pyfakefs/tests/import_as_example.py
index c358a30..74f9505 100644
--- a/pyfakefs/tests/import_as_example.py
+++ b/pyfakefs/tests/import_as_example.py
@@ -22,7 +22,7 @@ from io import open as io_open
from os import path
from os import stat
from os import stat as my_stat
-from os.path import exists
+from os.path import exists, isfile, isdir, islink
from os.path import exists as my_exists
from pathlib import Path
@@ -61,6 +61,21 @@ def check_if_exists7(filepath):
return pathlib.Path(filepath).exists()
+def check_if_isfile(filepath):
+ # tests patching `isfile` imported from os.path
+ return isfile(filepath)
+
+
+def check_if_isdir(filepath):
+ # tests patching `isdir` imported from os.path
+ return isdir(filepath)
+
+
+def check_if_islink(filepath):
+ # tests patching `islink` imported from os.path
+ return islink(filepath)
+
+
def file_stat1(filepath):
# tests patching `stat` imported from os
return stat(filepath)
@@ -72,7 +87,7 @@ def file_stat2(filepath):
def system_stat(filepath):
- if sys.platform == 'win32':
+ if sys.platform == "win32":
from nt import stat as system_stat
else:
from posix import stat as system_stat
diff --git a/pyfakefs/tests/logsio.py b/pyfakefs/tests/logsio.py
index 53f4e7a..15f704d 100644
--- a/pyfakefs/tests/logsio.py
+++ b/pyfakefs/tests/logsio.py
@@ -18,5 +18,5 @@ a name ending with "io" was skipped from patching (see #569).
def file_contents(path):
"""Return the contents of the given path as byte array."""
- with open(path, 'rb') as f:
+ with open(path, "rb") as f:
return f.read()
diff --git a/pyfakefs/tests/mox3_stubout_test.py b/pyfakefs/tests/mox3_stubout_test.py
index 4c09246..3382001 100644
--- a/pyfakefs/tests/mox3_stubout_test.py
+++ b/pyfakefs/tests/mox3_stubout_test.py
@@ -58,22 +58,18 @@ class StubOutForTestingTest(unittest.TestCase):
self.stubber = mox3_stubout.StubOutForTesting()
def test_stubout_method_with_set(self):
- non_existing_path = 'non_existing_path'
- self.assertFalse(
- mox3_stubout_example.check_if_exists(non_existing_path))
- self.stubber.set(os.path, 'exists', lambda x: True)
- self.assertTrue(
- mox3_stubout_example.check_if_exists(non_existing_path))
+ non_existing_path = "non_existing_path"
+ self.assertFalse(mox3_stubout_example.check_if_exists(non_existing_path))
+ self.stubber.set(os.path, "exists", lambda x: True)
+ self.assertTrue(mox3_stubout_example.check_if_exists(non_existing_path))
self.stubber.unset_all()
- self.assertFalse(
- mox3_stubout_example.check_if_exists(non_existing_path))
+ self.assertFalse(mox3_stubout_example.check_if_exists(non_existing_path))
def test_stubout_class_with_set(self):
self.assertGreater(mox3_stubout_example.tomorrow().year, 2000)
- self.stubber.set(datetime, 'date', GroundhogDate)
- self.assertEqual(mox3_stubout_example.tomorrow(),
- datetime.date(1993, 2, 3))
+ self.stubber.set(datetime, "date", GroundhogDate)
+ self.assertEqual(mox3_stubout_example.tomorrow(), datetime.date(1993, 2, 3))
self.stubber.unset_all()
self.assertGreater(mox3_stubout_example.tomorrow().year, 2000)
@@ -81,33 +77,45 @@ class StubOutForTestingTest(unittest.TestCase):
def test_stubout_module_with_set(self):
self.assertEqual(10, mox3_stubout_example.fabs(-10))
- self.stubber.set(mox3_stubout_example, 'math', NoPanicMath)
+ self.stubber.set(mox3_stubout_example, "math", NoPanicMath)
self.assertEqual(42, mox3_stubout_example.fabs(-10))
self.stubber.unset_all()
self.assertEqual(10, mox3_stubout_example.fabs(-10))
def test_set_raise_if_unknown_attribute(self):
- self.assertRaises(AttributeError, self.stubber.set,
- os.path, 'exists_not', lambda x: True)
- self.assertRaises(AttributeError, self.stubber.set,
- datetime, 'tomorrow', GroundhogDate)
- self.assertRaises(AttributeError, self.stubber.set,
- mox3_stubout_example, 'math1', NoPanicMath)
+ self.assertRaises(
+ AttributeError,
+ self.stubber.set,
+ os.path,
+ "exists_not",
+ lambda x: True,
+ )
+ self.assertRaises(
+ AttributeError,
+ self.stubber.set,
+ datetime,
+ "tomorrow",
+ GroundhogDate,
+ )
+ self.assertRaises(
+ AttributeError,
+ self.stubber.set,
+ mox3_stubout_example,
+ "math1",
+ NoPanicMath,
+ )
def test_stubout_method_with_smart_set(self):
- non_existing_path = 'non_existing_path'
- self.stubber.smart_set(os.path, 'exists', lambda x: True)
- self.assertTrue(
- mox3_stubout_example.check_if_exists(non_existing_path))
+ non_existing_path = "non_existing_path"
+ self.stubber.smart_set(os.path, "exists", lambda x: True)
+ self.assertTrue(mox3_stubout_example.check_if_exists(non_existing_path))
self.stubber.smart_unset_all()
- self.assertFalse(
- mox3_stubout_example.check_if_exists(non_existing_path))
+ self.assertFalse(mox3_stubout_example.check_if_exists(non_existing_path))
def test_stubout_class_with_smart_set(self):
- self.stubber.smart_set(datetime, 'date', GroundhogDate)
- self.assertEqual(mox3_stubout_example.tomorrow(),
- datetime.date(1993, 2, 3))
+ self.stubber.smart_set(datetime, "date", GroundhogDate)
+ self.assertEqual(mox3_stubout_example.tomorrow(), datetime.date(1993, 2, 3))
self.stubber.smart_unset_all()
self.assertGreater(mox3_stubout_example.tomorrow().year, 2000)
@@ -115,7 +123,7 @@ class StubOutForTestingTest(unittest.TestCase):
def test_stubout_module_with_smart_set(self):
self.assertEqual(10, mox3_stubout_example.fabs(-10))
- self.stubber.smart_set(mox3_stubout_example, 'math', NoPanicMath)
+ self.stubber.smart_set(mox3_stubout_example, "math", NoPanicMath)
self.assertEqual(42, mox3_stubout_example.fabs(-10))
self.stubber.smart_unset_all()
@@ -123,24 +131,36 @@ class StubOutForTestingTest(unittest.TestCase):
def test_stubout_submodule_with_smart_set(self):
# this one does not work with Set
- non_existing_path = 'non_existing_path'
- self.assertFalse(
- mox3_stubout_example.check_if_exists(non_existing_path))
- self.stubber.smart_set(os, 'path', ExistingPath)
- self.assertTrue(
- mox3_stubout_example.check_if_exists(non_existing_path))
+ non_existing_path = "non_existing_path"
+ self.assertFalse(mox3_stubout_example.check_if_exists(non_existing_path))
+ self.stubber.smart_set(os, "path", ExistingPath)
+ self.assertTrue(mox3_stubout_example.check_if_exists(non_existing_path))
self.stubber.smart_unset_all()
- self.assertFalse(
- mox3_stubout_example.check_if_exists(non_existing_path))
+ self.assertFalse(mox3_stubout_example.check_if_exists(non_existing_path))
def test_smart_set_raise_if_unknown_attribute(self):
- self.assertRaises(AttributeError, self.stubber.smart_set,
- os.path, 'exists_not', lambda x: True)
- self.assertRaises(AttributeError, self.stubber.smart_set,
- datetime, 'tomorrow', GroundhogDate)
- self.assertRaises(AttributeError, self.stubber.smart_set,
- mox3_stubout_example, 'math1', NoPanicMath)
-
-
-if __name__ == '__main__':
+ self.assertRaises(
+ AttributeError,
+ self.stubber.smart_set,
+ os.path,
+ "exists_not",
+ lambda x: True,
+ )
+ self.assertRaises(
+ AttributeError,
+ self.stubber.smart_set,
+ datetime,
+ "tomorrow",
+ GroundhogDate,
+ )
+ self.assertRaises(
+ AttributeError,
+ self.stubber.smart_set,
+ mox3_stubout_example,
+ "math1",
+ NoPanicMath,
+ )
+
+
+if __name__ == "__main__":
unittest.main()
diff --git a/pyfakefs/tests/patched_packages_test.py b/pyfakefs/tests/patched_packages_test.py
index f8d8a1a..1c76091 100644
--- a/pyfakefs/tests/patched_packages_test.py
+++ b/pyfakefs/tests/patched_packages_test.py
@@ -15,8 +15,11 @@ Provides patches for some commonly used modules that enable them to work
with pyfakefs.
"""
import os
+import sys
+import unittest
from pyfakefs import fake_filesystem_unittest
+from pyfakefs.helpers import IS_PYPY
try:
import pandas as pd
@@ -34,28 +37,33 @@ except ImportError:
openpyxl = None
+@unittest.skipIf(
+ IS_PYPY and sys.version_info < (3, 8), "Has a problem with older PyPy versions"
+)
class TestPatchedPackages(fake_filesystem_unittest.TestCase):
def setUp(self):
self.setUpPyfakefs()
if pd is not None:
+
def test_read_csv(self):
- path = '/foo/bar.csv'
- self.fs.create_file(path, contents='1,2,3,4')
+ path = "/foo/bar.csv"
+ self.fs.create_file(path, contents="1,2,3,4")
df = pd.read_csv(path)
- assert (df.columns == ['1', '2', '3', '4']).all()
+ assert (df.columns == ["1", "2", "3", "4"]).all()
def test_read_table(self):
- path = '/foo/bar.csv'
- self.fs.create_file(path, contents='1|2|3|4')
- df = pd.read_table(path, delimiter='|')
- assert (df.columns == ['1', '2', '3', '4']).all()
+ path = "/foo/bar.csv"
+ self.fs.create_file(path, contents="1|2|3|4")
+ df = pd.read_table(path, delimiter="|")
+ assert (df.columns == ["1", "2", "3", "4"]).all()
if pd is not None and xlrd is not None:
+
def test_read_excel(self):
- path = '/foo/bar.xlsx'
+ path = "/foo/bar.xlsx"
src_path = os.path.dirname(os.path.abspath(__file__))
- src_path = os.path.join(src_path, 'fixtures', 'excel_test.xlsx')
+ src_path = os.path.join(src_path, "fixtures", "excel_test.xlsx")
# map the file into another location to be sure that
# the real fs is not used
self.fs.add_real_file(src_path, target_path=path)
@@ -63,11 +71,12 @@ class TestPatchedPackages(fake_filesystem_unittest.TestCase):
assert (df.columns == [1, 2, 3, 4]).all()
if pd is not None and openpyxl is not None:
+
def test_write_excel(self):
- self.fs.create_dir('/foo')
- path = '/foo/bar.xlsx'
+ self.fs.create_dir("/foo")
+ path = "/foo/bar.xlsx"
df = pd.DataFrame([[0, 1, 2, 3]])
with pd.ExcelWriter(path) as writer:
df.to_excel(writer)
df = pd.read_excel(path)
- assert (df.columns == ['Unnamed: 0', 0, 1, 2, 3]).all()
+ assert (df.columns == ["Unnamed: 0", 0, 1, 2, 3]).all()
diff --git a/pyfakefs/tests/performance_test.py b/pyfakefs/tests/performance_test.py
index 5d0c67c..5e44f22 100644
--- a/pyfakefs/tests/performance_test.py
+++ b/pyfakefs/tests/performance_test.py
@@ -17,7 +17,7 @@ import unittest
from pyfakefs.fake_filesystem_unittest import TestCase
from pyfakefs.helpers import IS_PYPY
-if os.environ.get('TEST_PERFORMANCE'):
+if os.environ.get("TEST_PERFORMANCE"):
class SetupPerformanceTest(TestCase):
@classmethod
@@ -27,8 +27,11 @@ if os.environ.get('TEST_PERFORMANCE'):
@classmethod
def tearDownClass(cls) -> None:
cls.elapsed_time = time.time() - cls.start_time
- print('Elapsed time per test for cached setup: {:.3f} ms'.format(
- cls.elapsed_time * 10))
+ print(
+ "Elapsed time per test for cached setup: {:.3f} ms".format(
+ cls.elapsed_time * 10
+ )
+ )
def setUp(self) -> None:
self.setUpPyfakefs()
@@ -41,13 +44,16 @@ if os.environ.get('TEST_PERFORMANCE'):
@classmethod
def tearDownClass(cls) -> None:
cls.elapsed_time = time.time() - cls.start_time
- print('Elapsed time per test for uncached setup: {:.3f} ms'.format(
- cls.elapsed_time * 10))
+ print(
+ "Elapsed time per test for uncached setup: {:.3f} ms".format(
+ cls.elapsed_time * 10
+ )
+ )
def setUp(self) -> None:
self.setUpPyfakefs(use_cache=False)
- @unittest.skipIf(IS_PYPY, 'PyPy times are not comparable')
+ @unittest.skipIf(IS_PYPY, "PyPy times are not comparable")
class TimePerformanceTest(TestCase):
"""Make sure performance degradation in setup is noticed.
The numbers are related to the CI builds and may fail in local builds.
diff --git a/pyfakefs/tests/test_utils.py b/pyfakefs/tests/test_utils.py
index eea81c4..9555efb 100644
--- a/pyfakefs/tests/test_utils.py
+++ b/pyfakefs/tests/test_utils.py
@@ -12,7 +12,8 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-
+# Disable attribute errors - attributes not be found in mixin (shall be cleaned up...)
+# pytype: disable=attribute-error
"""Common helper classes used in tests, or as test class base."""
import os
import platform
@@ -24,7 +25,7 @@ import unittest
from contextlib import contextmanager
from unittest import mock
-from pyfakefs import fake_filesystem
+from pyfakefs import fake_filesystem, fake_open, fake_os
from pyfakefs.helpers import is_byte_string, to_string
@@ -56,15 +57,15 @@ class DummyMock:
def time_mock(start=200, step=20):
- return mock.patch('pyfakefs.fake_filesystem.now',
- DummyTime(start, step))
+ return mock.patch("pyfakefs.helpers.now", DummyTime(start, step))
class TestCase(unittest.TestCase):
"""Test base class with some convenience methods and attributes"""
- is_windows = sys.platform == 'win32'
- is_cygwin = sys.platform == 'cygwin'
- is_macos = sys.platform == 'darwin'
+
+ is_windows = sys.platform == "win32"
+ is_cygwin = sys.platform == "cygwin"
+ is_macos = sys.platform == "darwin"
symlinks_can_be_tested = None
def assert_mode_equal(self, expected, actual):
@@ -74,18 +75,7 @@ class TestCase(unittest.TestCase):
def raises_os_error(self, subtype):
try:
yield
- self.fail('No exception was raised, OSError expected')
- except OSError as exc:
- if isinstance(subtype, list):
- self.assertIn(exc.errno, subtype)
- else:
- self.assertEqual(subtype, exc.errno)
-
- def assert_raises_os_error(self, subtype, expression, *args, **kwargs):
- """Asserts that a specific subtype of OSError is raised."""
- try:
- expression(*args, **kwargs)
- self.fail('No exception was raised, OSError expected')
+ self.fail("No exception was raised, OSError expected")
except OSError as exc:
if isinstance(subtype, list):
self.assertIn(exc.errno, subtype)
@@ -115,7 +105,7 @@ class RealFsTestMixin:
self.base_path = None
def setUp(self):
- if not os.environ.get('TEST_REAL_FS'):
+ if not os.environ.get("TEST_REAL_FS"):
self.skip_real_fs()
if self.use_real_fs():
self.base_path = tempfile.mkdtemp()
@@ -132,9 +122,9 @@ class RealFsTestMixin:
def set_windows_fs(self, value):
if self.filesystem is not None:
- self.filesystem.is_windows_fs = value
+ self.filesystem._is_windows_fs = value
if value:
- self.filesystem.is_macos = False
+ self.filesystem._is_macos = False
self.create_basepath()
@property
@@ -143,18 +133,21 @@ class RealFsTestMixin:
@property
def is_pypy(self):
- return platform.python_implementation() == 'PyPy'
+ return platform.python_implementation() == "PyPy"
def use_real_fs(self):
"""Return True if the real file system shall be tested."""
return False
+ def setUpFileSystem(self):
+ pass
+
def path_separator(self):
"""Can be overwritten to use a specific separator in the
fake filesystem."""
if self.use_real_fs():
return os.path.sep
- return '/'
+ return "/"
def check_windows_only(self):
"""If called at test start, the real FS test is executed only under
@@ -162,8 +155,7 @@ class RealFsTestMixin:
"""
if self.use_real_fs():
if not TestCase.is_windows:
- raise unittest.SkipTest(
- 'Testing Windows specific functionality')
+ raise unittest.SkipTest("Testing Windows specific functionality")
else:
self.set_windows_fs(True)
@@ -173,11 +165,10 @@ class RealFsTestMixin:
"""
if self.use_real_fs():
if TestCase.is_macos or TestCase.is_windows:
- raise unittest.SkipTest(
- 'Testing Linux specific functionality')
+ raise unittest.SkipTest("Testing Linux specific functionality")
else:
self.set_windows_fs(False)
- self.filesystem.is_macos = False
+ self.filesystem._is_macos = False
def check_macos_only(self):
"""If called at test start, the real FS test is executed only under
@@ -185,11 +176,10 @@ class RealFsTestMixin:
"""
if self.use_real_fs():
if not TestCase.is_macos:
- raise unittest.SkipTest(
- 'Testing MacOS specific functionality')
+ raise unittest.SkipTest("Testing MacOS specific functionality")
else:
self.set_windows_fs(False)
- self.filesystem.is_macos = True
+ self.filesystem._is_macos = True
def check_linux_and_windows(self):
"""If called at test start, the real FS test is executed only under
@@ -198,10 +188,9 @@ class RealFsTestMixin:
"""
if self.use_real_fs():
if TestCase.is_macos:
- raise unittest.SkipTest(
- 'Testing non-MacOs functionality')
+ raise unittest.SkipTest("Testing non-MacOs functionality")
else:
- self.filesystem.is_macos = False
+ self.filesystem._is_macos = False
def check_case_insensitive_fs(self):
"""If called at test start, the real FS test is executed only in a
@@ -211,7 +200,8 @@ class RealFsTestMixin:
if self.use_real_fs():
if not TestCase.is_macos and not TestCase.is_windows:
raise unittest.SkipTest(
- 'Testing case insensitive specific functionality')
+ "Testing case insensitive specific functionality"
+ )
else:
self.filesystem.is_case_sensitive = False
@@ -222,8 +212,7 @@ class RealFsTestMixin:
"""
if self.use_real_fs():
if TestCase.is_macos or TestCase.is_windows:
- raise unittest.SkipTest(
- 'Testing case sensitive specific functionality')
+ raise unittest.SkipTest("Testing case sensitive specific functionality")
else:
self.filesystem.is_case_sensitive = True
@@ -234,33 +223,44 @@ class RealFsTestMixin:
"""
if self.use_real_fs():
if TestCase.is_windows:
- raise unittest.SkipTest(
- 'Testing Posix specific functionality')
+ raise unittest.SkipTest("Testing Posix specific functionality")
else:
self.set_windows_fs(False)
def skip_real_fs(self):
"""If called at test start, no real FS test is executed."""
if self.use_real_fs():
- raise unittest.SkipTest('Only tests fake FS')
-
- def skip_real_fs_failure(self, skip_windows=True, skip_posix=True,
- skip_macos=True, skip_linux=True):
+ raise unittest.SkipTest("Only tests fake FS")
+
+ def skip_real_fs_failure(
+ self,
+ skip_windows=True,
+ skip_posix=True,
+ skip_macos=True,
+ skip_linux=True,
+ ):
"""If called at test start, no real FS test is executed for the given
conditions. This is used to mark tests that do not pass correctly under
certain systems and shall eventually be fixed.
"""
if True:
- if (self.use_real_fs() and
- (TestCase.is_windows and skip_windows or
- not TestCase.is_windows
- and skip_macos and skip_linux or
- TestCase.is_macos and skip_macos or
- not TestCase.is_windows and
- not TestCase.is_macos and skip_linux or
- not TestCase.is_windows and skip_posix)):
+ if self.use_real_fs() and (
+ TestCase.is_windows
+ and skip_windows
+ or not TestCase.is_windows
+ and skip_macos
+ and skip_linux
+ or TestCase.is_macos
+ and skip_macos
+ or not TestCase.is_windows
+ and not TestCase.is_macos
+ and skip_linux
+ or not TestCase.is_windows
+ and skip_posix
+ ):
raise unittest.SkipTest(
- 'Skipping because FakeFS does not match real FS')
+ "Skipping because FakeFS does not match real FS"
+ )
def symlink_can_be_tested(self, force_real_fs=False):
"""Used to check if symlinks and hard links can be tested under
@@ -268,13 +268,12 @@ class RealFsTestMixin:
not supporting links, and real tests are skipped if running without
administrator rights.
"""
- if (not TestCase.is_windows or
- (not force_real_fs and not self.use_real_fs())):
+ if not TestCase.is_windows or (not force_real_fs and not self.use_real_fs()):
return True
if TestCase.symlinks_can_be_tested is None:
if force_real_fs:
self.base_path = tempfile.mkdtemp()
- link_path = self.make_path('link')
+ link_path = self.make_path("link")
try:
self.os.symlink(self.base_path, link_path)
TestCase.symlinks_can_be_tested = True
@@ -289,8 +288,7 @@ class RealFsTestMixin:
"""If called at test start, tests are skipped if symlinks are not
supported."""
if not self.symlink_can_be_tested(force_real_fs):
- raise unittest.SkipTest(
- 'Symlinks under Windows need admin privileges')
+ raise unittest.SkipTest("Symlinks under Windows need admin privileges")
def make_path(self, *args):
"""Create a path with the given component(s). A base path is prepended
@@ -307,10 +305,12 @@ class RealFsTestMixin:
args = [to_string(arg) for arg in args]
return self.os.path.join(self.base_path, *args)
- def create_dir(self, dir_path):
+ def create_dir(self, dir_path, perm=0o777):
"""Create the directory at `dir_path`, including subdirectories.
`dir_path` shall be composed using `make_path()`.
"""
+ if not dir_path:
+ return
existing_path = dir_path
components = []
while existing_path and not self.os.path.exists(existing_path):
@@ -325,6 +325,7 @@ class RealFsTestMixin:
existing_path = self.os.path.join(existing_path, component)
self.os.mkdir(existing_path)
self.os.chmod(existing_path, 0o777)
+ self.os.chmod(dir_path, perm)
def create_file(self, file_path, contents=None, encoding=None, perm=0o666):
"""Create the given file at `file_path` with optional contents,
@@ -332,8 +333,7 @@ class RealFsTestMixin:
`make_path()`.
"""
self.create_dir(self.os.path.dirname(file_path))
- mode = ('wb' if encoding is not None or is_byte_string(contents)
- else 'w')
+ mode = "wb" if encoding is not None or is_byte_string(contents) else "w"
if encoding is not None and contents is not None:
contents = contents.encode(encoding)
@@ -353,7 +353,7 @@ class RealFsTestMixin:
"""Compare `contents` with the contents of the file at `file_path`.
Asserts equality.
"""
- mode = 'rb' if is_byte_string(contents) else 'r'
+ mode = "rb" if is_byte_string(contents) else "r"
with self.open(file_path, mode) as f:
self.assertEqual(contents, f.read())
@@ -361,9 +361,9 @@ class RealFsTestMixin:
"""Create the path used as base path in `make_path`."""
if self.filesystem is not None:
old_base_path = self.base_path
- self.base_path = self.filesystem.path_separator + 'basepath'
- if self.is_windows_fs:
- self.base_path = 'C:' + self.base_path
+ self.base_path = self.filesystem.path_separator + "basepath"
+ if self.filesystem.is_windows_fs:
+ self.base_path = "C:" + self.base_path
if old_base_path != self.base_path:
if old_base_path is not None:
self.filesystem.reset()
@@ -374,18 +374,22 @@ class RealFsTestMixin:
def assert_equal_paths(self, actual, expected):
if self.is_windows:
- actual = str(actual).replace('\\\\?\\', '')
- expected = str(expected).replace('\\\\?\\', '')
- if os.name == 'nt' and self.use_real_fs():
+ actual = str(actual).replace("\\\\?\\", "")
+ expected = str(expected).replace("\\\\?\\", "")
+ if os.name == "nt" and self.use_real_fs():
# work around a problem that the user name, but not the full
# path is shown as the short name
- self.assertEqual(self.path_with_short_username(actual),
- self.path_with_short_username(expected))
+ self.assertEqual(
+ self.path_with_short_username(actual),
+ self.path_with_short_username(expected),
+ )
else:
self.assertEqual(actual, expected)
elif self.is_macos:
- self.assertEqual(str(actual).replace('/private/var/', '/var/'),
- str(expected).replace('/private/var/', '/var/'))
+ self.assertEqual(
+ str(actual).replace("/private/var/", "/var/"),
+ str(expected).replace("/private/var/", "/var/"),
+ )
else:
self.assertEqual(actual, expected)
@@ -393,21 +397,31 @@ class RealFsTestMixin:
def path_with_short_username(path):
components = path.split(os.sep)
if len(components) >= 3:
- components[2] = components[2][:6].upper() + '~1'
+ components[2] = components[2][:6].upper() + "~1"
return os.sep.join(components)
def mock_time(self, start=200, step=20):
if not self.use_real_fs():
- return mock.patch('pyfakefs.fake_filesystem.now',
- DummyTime(start, step))
+ return time_mock(start, step)
return DummyMock()
+ def assert_raises_os_error(self, subtype, expression, *args, **kwargs):
+ """Asserts that a specific subtype of OSError is raised."""
+ try:
+ expression(*args, **kwargs)
+ self.fail("No exception was raised, OSError expected")
+ except OSError as exc:
+ if isinstance(subtype, list):
+ self.assertIn(exc.errno, subtype)
+ else:
+ self.assertEqual(subtype, exc.errno)
+
class RealFsTestCase(TestCase, RealFsTestMixin):
"""Can be used as base class for tests also running in the real
file system."""
- def __init__(self, methodName='runTest'):
+ def __init__(self, methodName="runTest"):
TestCase.__init__(self, methodName)
RealFsTestMixin.__init__(self)
@@ -416,19 +430,20 @@ class RealFsTestCase(TestCase, RealFsTestMixin):
self.cwd = os.getcwd()
if not self.use_real_fs():
self.filesystem = fake_filesystem.FakeFilesystem(
- path_separator=self.path_separator())
- self.open = fake_filesystem.FakeFileOpen(self.filesystem)
- self.os = fake_filesystem.FakeOsModule(self.filesystem)
- self.create_basepath()
-
+ path_separator=self.path_separator()
+ )
+ self.setup_fake_fs()
self.setUpFileSystem()
+ def setup_fake_fs(self):
+ if not self.use_real_fs():
+ self.open = fake_open.FakeFileOpen(self.filesystem)
+ self.os = fake_os.FakeOsModule(self.filesystem)
+ self.create_basepath()
+
def tearDown(self):
RealFsTestMixin.tearDown(self)
- def setUpFileSystem(self):
- pass
-
@property
def is_windows_fs(self):
if self.use_real_fs():
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..fed528d
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["setuptools"]
+build-backend = "setuptools.build_meta"
diff --git a/requirements.txt b/requirements.txt
index 3bfb271..b949482 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1 @@
-pytest>=2.8.6
+pytest>=3.0.0
diff --git a/requirements_dev.txt b/requirements_dev.txt
new file mode 100644
index 0000000..eb37ab8
--- /dev/null
+++ b/requirements_dev.txt
@@ -0,0 +1 @@
+pre-commit==3.3.3
diff --git a/setup.cfg b/setup.cfg
index 0379a60..a45a048 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,4 +1,64 @@
[metadata]
-description_file = README.md
+name = pyfakefs
+version = attr: pyfakefs.__version__
+author = Google
+author_email = google-pyfakefs@google.com
+maintainer = John McGehee
+maintainer_email = pyfakefs@johnnado.com
+license = http://www.apache.org/licenses/LICENSE-2.0
+description = pyfakefs implements a fake file system that mocks the Python file system modules.
+long_description = file: README.md
+long_description_content_type = text/markdown
+keywords =
+ testing
+ test
+ file
+ os
+ shutil
+ pathlib
+ mocking
+ unittest
+ pytest
+ fakes
+ filesystem
+url = https://github.com/pytest-dev/pyfakefs
+classifiers =
+ Development Status :: 5 - Production/Stable
+ Environment :: Console
+ Intended Audience :: Developers
+ License :: OSI Approved :: Apache Software License
+ Programming Language :: Python :: 3
+ Programming Language :: Python :: 3.8
+ Programming Language :: Python :: 3.9
+ Programming Language :: Python :: 3.10
+ Programming Language :: Python :: 3.11
+ Programming Language :: Python :: Implementation :: CPython
+ Programming Language :: Python :: Implementation :: PyPy
+ Operating System :: POSIX
+ Operating System :: MacOS
+ Operating System :: Microsoft :: Windows
+ Topic :: Software Development :: Libraries
+ Topic :: Software Development :: Libraries :: Python Modules
+ Topic :: Software Development :: Testing
+ Topic :: System :: Filesystems
+ Framework :: Pytest
+
[bdist_wheel]
-universal=0
+universal = 0
+
+[options]
+packages = find:
+install_requires =
+python_requires = >=3.8
+test_suite = pyfakefs.tests
+include_package_data = True
+
+[options.packages.find]
+exclude = docs
+
+[options.package_data]
+pyfakefs = py.typed
+
+[options.entry_points]
+pytest11 =
+ pytest_fakefs = pyfakefs.pytest_plugin
diff --git a/setup.py b/setup.py
index 61060ec..7f1a176 100644
--- a/setup.py
+++ b/setup.py
@@ -1,91 +1,4 @@
-#! /usr/bin/env python
+from setuptools import setup
-# Copyright 2009 Google Inc. All Rights Reserved.
-# Copyright 2014 Altera Corporation. All Rights Reserved.
-# Copyright 2014-2018 John McGehee
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-import os
-from typing import List
-
-from setuptools import setup, find_packages
-
-from pyfakefs import __version__
-
-NAME = 'pyfakefs'
-REQUIRES: List[str] = []
-DESCRIPTION = ('pyfakefs implements a fake file system that mocks '
- 'the Python file system modules.')
-
-URL = "http://pyfakefs.org"
-
-BASE_PATH = os.path.abspath(os.path.dirname(__file__))
-with open(os.path.join(BASE_PATH, 'README.md')) as f:
- LONG_DESCRIPTION = f.read()
-
-CLASSIFIERS = [
- 'Development Status :: 5 - Production/Stable',
- 'Environment :: Console',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Apache Software License',
- "Programming Language :: Python :: 3",
- 'Programming Language :: Python :: 3.6',
- 'Programming Language :: Python :: 3.7',
- 'Programming Language :: Python :: 3.8',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: Implementation :: CPython',
- 'Programming Language :: Python :: Implementation :: PyPy',
- 'Operating System :: POSIX',
- 'Operating System :: MacOS',
- 'Operating System :: Microsoft :: Windows',
- 'Topic :: Software Development :: Libraries',
- 'Topic :: Software Development :: Libraries :: Python Modules',
- 'Topic :: Software Development :: Testing',
- 'Topic :: System :: Filesystems',
- 'Framework :: Pytest',
-]
-
-AUTHOR = 'Google'
-AUTHOR_EMAIL = 'google-pyfakefs@google.com'
-MAINTAINER = 'John McGehee'
-MAINTAINER_EMAIL = 'pyfakefs@johnnado.com'
-KEYWORDS = ("testing test file os shutil glob mocking unittest "
- "fakes filesystem unit").split(' ')
-
-params = dict(
- name=NAME,
- entry_points={
- 'pytest11': ['pytest_fakefs = pyfakefs.pytest_plugin'],
- },
- version=__version__,
- install_requires=REQUIRES,
-
- # metadata for upload to PyPI
- author=AUTHOR,
- author_email=AUTHOR_EMAIL,
- maintainer=MAINTAINER,
- maintainer_email=MAINTAINER_EMAIL,
- license='http://www.apache.org/licenses/LICENSE-2.0',
- description=DESCRIPTION,
- long_description=LONG_DESCRIPTION,
- long_description_content_type='text/markdown',
- keywords=KEYWORDS,
- url=URL,
- classifiers=CLASSIFIERS,
- python_requires='>=3.6',
- test_suite='pyfakefs.tests',
- packages=find_packages(exclude=['docs'])
-)
-
-setup(**params)
+if __name__ == "__main__":
+ setup()
diff --git a/tox.ini b/tox.ini
index c5c0c90..ccc165e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,11 +1,11 @@
[tox]
-envlist=py36,py37,py38,py39,py310,pypy3
+envlist = py37,py38,py39,py310,py311,pypy3
[testenv]
deps =
-rrequirements.txt
-rextra_requirements.txt
-passenv = HOME USERPROFILE
+passenv = HOME,USERPROFILE
commands=
python -m pyfakefs.tests.all_tests
python -m pyfakefs.tests.all_tests_without_extra_packages