Skip to content

Regressions related to URL formation in Python 3.14 #596

Description

@musicinmybrain

To demonstrate this, I first have to get the tests working on Python 3.13. I skip ftpfs download tests to avoid flaky failures noted in #595.

$ git clone https://github.com/PyFilesystem/pyfilesystem2.git
$ cd pyfilesystem2
$ git branch py314
$ git checkout py314
$ curl -L -O https://github.com/PyFilesystem/pyfilesystem2/pull/570.patch
$ git am 570.patch
$ curl -L -O https://github.com/PyFilesystem/pyfilesystem2/pull/587.patch
$ git am 587.patch
$ curl -L -O https://github.com/PyFilesystem/pyfilesystem2/pull/595.patch
$ git am 595.patch
$ python3 --version
Python 3.13.3
$ python3 -m venv _e
$ . _e/bin/activate
(_e) $ pip install -e .
(_e) $ pip install -r tests/requirements.txt pytest
(_e) $ pytest -k 'not TestFTPFS'
[…]
=================== 2463 passed, 24 skipped, 193 deselected, 32 warnings in 15.70s ===================

Now, repeating the same steps with Python 3.14:

(_e) $ deactivate
$ python3.14 --version
Python 3.14.0b2
$ python3.14 -m venv _f
$ . _f/bin/activate
(_f) $ pip install -e .
(_f) $ pip install -r tests/requirements.txt pytest
(_f) $ pytest -k 'not TestFTPFS'
[…]
tests/test_ftpfs.py ..Fatal Python error: Segmentation fault
Current thread 0x00007ffaff251bc0 [pytest] (most recent call first):
File "/home/ben/src/forks/pyfilesystem2/_f/lib64/python3.14/site-packages/cryptography/hazmat/bindings/openssl/binding.py", line 50 in build_conditional_library
File "/home/ben/src/forks/pyfilesystem2/_f/lib64/python3.14/site-packages/cryptography/hazmat/bindings/openssl/binding.py", line 72 in _ensure_ffi_initialized
File "/home/ben/src/forks/pyfilesystem2/_f/lib64/python3.14/site-packages/cryptography/hazmat/bindings/openssl/binding.py", line 79 in init_static_locks
File "/home/ben/src/forks/pyfilesystem2/_f/lib64/python3.14/site-packages/cryptography/hazmat/bindings/openssl/binding.py", line 110 in <module>
[…]

Ok, that appears to be an issue with the current PyPI wheels for cryptography; let’s omit tests/test_ftpfs.py entirely for now.

(_f) $ pytest --ignore tests/test_ftpfs.py
[…]
============================================== FAILURES ==============================================
____________________________________ TestOSFS.test_complex_geturl ____________________________________
self = <tests.test_osfs.TestOSFS testMethod=test_complex_geturl>
def test_complex_geturl(self):
self.fs.makedirs("foo/bar ha")
test_fixtures = [
# test file, expected url path
["foo", "foo"],
["foo-bar", "foo-bar"],
["foo_bar", "foo_bar"],
["foo/bar ha/barz", "foo/bar%20ha/barz"],
["example b.txt", "example%20b.txt"],
["exampleㄓ.txt", "example%E3%84%93.txt"],
]
file_uri_prefix = "osfs://"
for test_file, relative_url_path in test_fixtures:
self.fs.create(test_file)
expected = file_uri_prefix + self.fs.getsyspath(relative_url_path).replace(
"\\", "/"
)
actual = self.fs.geturl(test_file, purpose="fs")
> self.assertEqual(actual, expected)
E AssertionError: 'osfs://///tmp/tmpmmeyh_87fstestosfs/foo' != 'osfs:///tmp/tmpmmeyh_87fstestosfs/foo'
E - osfs://///tmp/tmpmmeyh_87fstestosfs/foo
E ? --
E + osfs:///tmp/tmpmmeyh_87fstestosfs/foo
tests/test_osfs.py:227: AssertionError
____________________________________ TestOSFS.test_complex_geturl ____________________________________
self = <tests.test_osfs.TestOSFS testMethod=test_complex_geturl>
def test_complex_geturl(self):
self.fs.makedirs("foo/bar ha")
test_fixtures = [
# test file, expected url path
["foo", "foo"],
["foo-bar", "foo-bar"],
["foo_bar", "foo_bar"],
["foo/bar ha/barz", "foo/bar%20ha/barz"],
["example b.txt", "example%20b.txt"],
["exampleㄓ.txt", "example%E3%84%93.txt"],
]
file_uri_prefix = "osfs://"
for test_file, relative_url_path in test_fixtures:
self.fs.create(test_file)
expected = file_uri_prefix + self.fs.getsyspath(relative_url_path).replace(
"\\", "/"
)
actual = self.fs.geturl(test_file, purpose="fs")
> self.assertEqual(actual, expected)
E AssertionError: 'osfs://///tmp/tmpqbdqe7a2fstestosfs/foo' != 'osfs:///tmp/tmpqbdqe7a2fstestosfs/foo'
E - osfs://///tmp/tmpqbdqe7a2fstestosfs/foo
E ? --
E + osfs:///tmp/tmpqbdqe7a2fstestosfs/foo
tests/test_osfs.py:227: AssertionError
___________________________________ TestSubFS.test_complex_geturl ____________________________________
self = <tests.test_subfs.TestSubFS testMethod=test_complex_geturl>
def test_complex_geturl(self):
self.fs.makedirs("foo/bar ha")
test_fixtures = [
# test file, expected url path
["foo", "foo"],
["foo-bar", "foo-bar"],
["foo_bar", "foo_bar"],
["foo/bar ha/barz", "foo/bar%20ha/barz"],
["example b.txt", "example%20b.txt"],
["exampleㄓ.txt", "example%E3%84%93.txt"],
]
file_uri_prefix = "osfs://"
for test_file, relative_url_path in test_fixtures:
self.fs.create(test_file)
expected = file_uri_prefix + self.fs.getsyspath(relative_url_path).replace(
"\\", "/"
)
actual = self.fs.geturl(test_file, purpose="fs")
> self.assertEqual(actual, expected)
E AssertionError: 'osfs://///tmp/tmprx2ztqhdfstest/__subdir__/foo' != 'osfs:///tmp/tmprx2ztqhdfstest/__subdir__/foo'
E - osfs://///tmp/tmprx2ztqhdfstest/__subdir__/foo
E ? --
E + osfs:///tmp/tmprx2ztqhdfstest/__subdir__/foo
tests/test_osfs.py:227: AssertionError
__________________________________ TestReadTarFS.test_geturl_for_fs __________________________________
self = <tests.test_tarfs.TestReadTarFS testMethod=test_geturl_for_fs>
def test_geturl_for_fs(self):
test_fixtures = [
# test_file, expected
["foo/bar/egg/foofoo", "foo/bar/egg/foofoo"],
["foo/bar egg/foo foo", "foo/bar%20egg/foo%20foo"],
]
tar_file_path = self._temp_path.replace("\\", "/")
for test_file, expected_file in test_fixtures:
expected = "tar://{tar_file_path}!/{file_inside_tar}".format(
tar_file_path=tar_file_path, file_inside_tar=expected_file
)
> self.assertEqual(self.fs.geturl(test_file, purpose="fs"), expected)
E AssertionError: 'tar://///tmp/tmp5z7bhtdw!/foo/bar/egg/foofoo' != 'tar:///tmp/tmp5z7bhtdw!/foo/bar/egg/foofoo'
E - tar://///tmp/tmp5z7bhtdw!/foo/bar/egg/foofoo
E ? --
E + tar:///tmp/tmp5z7bhtdw!/foo/bar/egg/foofoo
tests/test_tarfs.py:208: AssertionError
________________________________ TestReadTarFSMem.test_geturl_for_fs _________________________________
self = <tests.test_tarfs.TestReadTarFSMem testMethod=test_geturl_for_fs>
def test_geturl_for_fs(self):
test_fixtures = [
# test_file, expected
["foo/bar/egg/foofoo", "foo/bar/egg/foofoo"],
["foo/bar egg/foo foo", "foo/bar%20egg/foo%20foo"],
]
tar_file_path = self._temp_path.replace("\\", "/")
for test_file, expected_file in test_fixtures:
expected = "tar://{tar_file_path}!/{file_inside_tar}".format(
tar_file_path=tar_file_path, file_inside_tar=expected_file
)
> self.assertEqual(self.fs.geturl(test_file, purpose="fs"), expected)
E AssertionError: 'tar://///tmp/tmpwa9u0aba!/foo/bar/egg/foofoo' != 'tar:///tmp/tmpwa9u0aba!/foo/bar/egg/foofoo'
E - tar://///tmp/tmpwa9u0aba!/foo/bar/egg/foofoo
E ? --
E + tar:///tmp/tmpwa9u0aba!/foo/bar/egg/foofoo
tests/test_tarfs.py:208: AssertionError
____________________________________ TestOSFS.test_complex_geturl ____________________________________
self = <tests.test_osfs.TestOSFS testMethod=test_complex_geturl>
def test_complex_geturl(self):
self.fs.makedirs("foo/bar ha")
test_fixtures = [
# test file, expected url path
["foo", "foo"],
["foo-bar", "foo-bar"],
["foo_bar", "foo_bar"],
["foo/bar ha/barz", "foo/bar%20ha/barz"],
["example b.txt", "example%20b.txt"],
["exampleㄓ.txt", "example%E3%84%93.txt"],
]
file_uri_prefix = "osfs://"
for test_file, relative_url_path in test_fixtures:
self.fs.create(test_file)
expected = file_uri_prefix + self.fs.getsyspath(relative_url_path).replace(
"\\", "/"
)
actual = self.fs.geturl(test_file, purpose="fs")
> self.assertEqual(actual, expected)
E AssertionError: 'osfs://///tmp/tmp9srq1bisfstestosfs/foo' != 'osfs:///tmp/tmp9srq1bisfstestosfs/foo'
E - osfs://///tmp/tmp9srq1bisfstestosfs/foo
E ? --
E + osfs:///tmp/tmp9srq1bisfstestosfs/foo
tests/test_osfs.py:227: AssertionError
___________________________________ TestTempFS.test_complex_geturl ___________________________________
self = <tests.test_tempfs.TestTempFS testMethod=test_complex_geturl>
def test_complex_geturl(self):
self.fs.makedirs("foo/bar ha")
test_fixtures = [
# test file, expected url path
["foo", "foo"],
["foo-bar", "foo-bar"],
["foo_bar", "foo_bar"],
["foo/bar ha/barz", "foo/bar%20ha/barz"],
["example b.txt", "example%20b.txt"],
["exampleㄓ.txt", "example%E3%84%93.txt"],
]
file_uri_prefix = "osfs://"
for test_file, relative_url_path in test_fixtures:
self.fs.create(test_file)
expected = file_uri_prefix + self.fs.getsyspath(relative_url_path).replace(
"\\", "/"
)
actual = self.fs.geturl(test_file, purpose="fs")
> self.assertEqual(actual, expected)
E AssertionError: 'osfs://///tmp/tmpu46lay_a__tempfs__/foo' != 'osfs:///tmp/tmpu46lay_a__tempfs__/foo'
E - osfs://///tmp/tmpu46lay_a__tempfs__/foo
E ? --
E + osfs:///tmp/tmpu46lay_a__tempfs__/foo
tests/test_osfs.py:227: AssertionError
__________________________________ TestReadZipFS.test_geturl_for_fs __________________________________
self = <tests.test_zipfs.TestReadZipFS testMethod=test_geturl_for_fs>
def test_geturl_for_fs(self):
test_file = "foo/bar/egg/foofoo"
expected = "zip://{zip_file_path}!/{file_inside_zip}".format(
zip_file_path=self._temp_path.replace("\\", "/"), file_inside_zip=test_file
)
> self.assertEqual(self.fs.geturl(test_file, purpose="fs"), expected)
E AssertionError: 'zip://///tmp/tmpn0pdowr6!/foo/bar/egg/foofoo' != 'zip:///tmp/tmpn0pdowr6!/foo/bar/egg/foofoo'
E - zip://///tmp/tmpn0pdowr6!/foo/bar/egg/foofoo
E ? --
E + zip:///tmp/tmpn0pdowr6!/foo/bar/egg/foofoo
tests/test_zipfs.py:177: AssertionError
________________________________ TestReadZipFSMem.test_geturl_for_fs _________________________________
self = <tests.test_zipfs.TestReadZipFSMem testMethod=test_geturl_for_fs>
def test_geturl_for_fs(self):
test_file = "foo/bar/egg/foofoo"
expected = "zip://{zip_file_path}!/{file_inside_zip}".format(
zip_file_path=self._temp_path.replace("\\", "/"), file_inside_zip=test_file
)
> self.assertEqual(self.fs.geturl(test_file, purpose="fs"), expected)
E AssertionError: 'zip://///tmp/tmpx8ggt4qv!/foo/bar/egg/foofoo' != 'zip:///tmp/tmpx8ggt4qv!/foo/bar/egg/foofoo'
E - zip://///tmp/tmpx8ggt4qv!/foo/bar/egg/foofoo
E ? --
E + zip:///tmp/tmpx8ggt4qv!/foo/bar/egg/foofoo
tests/test_zipfs.py:177: AssertionError
========================================== warnings summary ==========================================
[…]
====================================== short test summary info =======================================
FAILED tests/test_osfs.py::TestOSFS::test_complex_geturl - AssertionError: 'osfs://///tmp/tmpmmeyh_87fstestosfs/foo' != 'osfs:///tmp/tmpmmeyh_87fstestosfs/foo'
FAILED tests/test_subfs.py::TestOSFS::test_complex_geturl - AssertionError: 'osfs://///tmp/tmpqbdqe7a2fstestosfs/foo' != 'osfs:///tmp/tmpqbdqe7a2fstestosfs/foo'
FAILED tests/test_subfs.py::TestSubFS::test_complex_geturl - AssertionError: 'osfs://///tmp/tmprx2ztqhdfstest/__subdir__/foo' != 'osfs:///tmp/tmprx2ztqhdfstes...
FAILED tests/test_tarfs.py::TestReadTarFS::test_geturl_for_fs - AssertionError: 'tar://///tmp/tmp5z7bhtdw!/foo/bar/egg/foofoo' != 'tar:///tmp/tmp5z7bhtdw!/foo/ba...
FAILED tests/test_tarfs.py::TestReadTarFSMem::test_geturl_for_fs - AssertionError: 'tar://///tmp/tmpwa9u0aba!/foo/bar/egg/foofoo' != 'tar:///tmp/tmpwa9u0aba!/foo/ba...
FAILED tests/test_tempfs.py::TestOSFS::test_complex_geturl - AssertionError: 'osfs://///tmp/tmp9srq1bisfstestosfs/foo' != 'osfs:///tmp/tmp9srq1bisfstestosfs/foo'
FAILED tests/test_tempfs.py::TestTempFS::test_complex_geturl - AssertionError: 'osfs://///tmp/tmpu46lay_a__tempfs__/foo' != 'osfs:///tmp/tmpu46lay_a__tempfs__/foo'
FAILED tests/test_zipfs.py::TestReadZipFS::test_geturl_for_fs - AssertionError: 'zip://///tmp/tmpn0pdowr6!/foo/bar/egg/foofoo' != 'zip:///tmp/tmpn0pdowr6!/foo/ba...
FAILED tests/test_zipfs.py::TestReadZipFSMem::test_geturl_for_fs - AssertionError: 'zip://///tmp/tmpx8ggt4qv!/foo/bar/egg/foofoo' != 'zip:///tmp/tmpx8ggt4qv!/foo/ba...
====================== 9 failed, 2365 passed, 23 skipped, 28 warnings in 14.53s ======================

All of these appear to be related to python/cpython#125974.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions