Skip to content

remove hard-dependency on pyfilesystem2, add a minimal drop-in replacement #3885

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 15, 2025

Conversation

anthrotype
Copy link
Member

This adds a new fontTools.misc.filesystem package that exposes the same API as pyfilesystem2 but only for the subset that fontTools.ufoLib uses: i.e. OSFS, SubFS, ZipFS, TempFS and other little helpers.

the requirement in setup.py was removed, so pip install fonttools[ufo] will no longer instal fs. However, the code continues to work with fs if one installs it separately and wishes to pass actual FS objects to ufoLib.

Similarly to what we do with lxml, I try to import fs and if that fails I fall back to this new fontTools.misc.filesystem. No other changes inside the fontTools.ufoLib code itself besides the try/import.

The CI runs test with and without fs. I think it's ok to continue supporting fs as a soft/optional dependency given that it still works (despite the pkg_resources deprecation warning), and it may be resurrected at some point.

But if one doesn't care about fancy fileststems but just UFO as local directories or zip, the fs module is no longer required basically and the warning shoud stop showing up.

@anthrotype
Copy link
Member Author

anthrotype commented Jul 10, 2025

OSFS is just a thin wrapper around pathlib.Path, whereas ZipFS uses zipfile to open and read specific files within the archive (without unpacking it all); for the zip writer, it's just a TempFS that calls shutil.make_archive on close() (not dissimilar from the original fs.ZipFS).

@anthrotype anthrotype marked this pull request as draft July 10, 2025 16:19
openbin -> open(mode=*b) so we have one fewer method to support;
fs.path.parts[-1] is the same as fs.path.basename, prefer the latter
@anthrotype anthrotype marked this pull request as ready for review July 11, 2025 12:58
@anthrotype anthrotype force-pushed the drop-fs branch 3 times, most recently from 2f4a238 to bb0b727 Compare July 14, 2025 15:14
@anthrotype
Copy link
Member Author

ok this is ready for review now. I tested ufoLib2 and defcon test suite and they just work with minor modification, notably stuff like

- import fs
+ from fontTools.misc import filesystem as fs

@madig
Copy link
Collaborator

madig commented Jul 15, 2025

Where did you get all the implementation code from? Did you copy-paste and prune fs's code?

@anthrotype
Copy link
Member Author

anthrotype commented Jul 15, 2025

well not literal copy paste, more like taking "inspiration" while aiming for the most concise approach to keep things working as before while using stdlib-only methods.. I could add citation links to original source code if you like.

EDIT: I added original copyright and license notice to LICENSE.external file: 6580a42

@madig
Copy link
Collaborator

madig commented Jul 15, 2025

No need, I just wondered how you hammered all that code out so quickly.

Copy link
Collaborator

@madig madig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@madig
Copy link
Collaborator

madig commented Jul 15, 2025

Oh BTW, you may want to run uv run ruff check --select I --fix . ; uv run ruff check --fix ; uv run ruff format over this code, just in case.

from fontTools.ufoLib.utils import numberTypes, _VersionTupleEnumMixin
from fontTools.ufoLib.filenames import userNameToFileName
from fontTools.ufoLib.utils import _VersionTupleEnumMixin, numberTypes
from fontTools.ufoLib.validators import *
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, maybe just import pngValidator?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah ruff didn't like the star-import..

…thout it

CI runs tox twice, the second time with -noextra which will not install any of the third-party deps listed in requirements.txt
... instead of try/except ImportError

either upstream `fs` module or our replacement is used depending on whether the former is available
we currently don't use this (why would one ever want to *not* create dst_dir...) but at least I removed a TODO :)
@anthrotype anthrotype merged commit e687881 into main Jul 15, 2025
11 checks passed
@anthrotype anthrotype deleted the drop-fs branch July 15, 2025 17:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants