Skip to content

Conversation

@anthrotype
Copy link
Member

@anthrotype anthrotype commented Jul 14, 2025

we are planning on dropping a hard dependency on fs module (pyfilesystem2) in fontTools.ufoLib since it is no longer maintained and is starting to issue a bunch of deprecation warnings (e.g. from pkg_resources scheduled for removal from setuptools in a few months).
I worked on writing a stdlib-only replacement for the subset of classes/functions that ufoLib is currently using here:
fonttools/fonttools#3885
If one does have fs installed, it will still be used for as long as it continues to work (like a "soft" or optional dependency).

Now I noticed defcon's own test suite imports from and calls fs methods directly in a bunch of places, that's ok.
However, no matter wheter one is using fs directly or its fallback replacement in fontTools.misc.filesytem, there are a few things that defcon's tests can do to simplify things a bit:

  1. calls to fs.path.join are unneeded, since what they do is basically just join with a UNIX-style forward slash "f{path1}/{path2}"; unlike os.path.join all the paths used by pyfilesystem2 internally are supposed to use forward slashes no matter the platform, so fs.path.join is not actually needed given defcon is passing it plain string literals without any '..' backreferences etc. Incidentally, I have one fewer function to port over to fontTools.misc.filesytem :)

  2. some tests use FS.glob() method to list all the "glyphs/*.glif" files, but the same can be achieved with listdir() and filtering results by whether endswith(".glif"). Again, implementing glob method properly in fontTools is too much work for not much gain...

After these changes, one can in theory replace all the direct import fs with a import fontTools.misc.filesystem as fs and everything works whether or not fs is actually installed.

@codecov-commenter
Copy link

codecov-commenter commented Jul 14, 2025

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 87.47%. Comparing base (ab82e93) to head (a40850f).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #468      +/-   ##
==========================================
- Coverage   87.47%   87.47%   -0.01%     
==========================================
  Files          57       57              
  Lines       10367    10364       -3     
  Branches     1338     1338              
==========================================
- Hits         9069     9066       -3     
  Misses        921      921              
  Partials      377      377              
Flag Coverage Δ
unittests 87.47% <100.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@anthrotype
Copy link
Member Author

after applying the following patch and pip uninstall -y fs the defcon test suite continues to pass:

diff --git a/Lib/defcon/test/objects/test_dataSet.py b/Lib/defcon/test/objects/test_dataSet.py
index 2f78965..a2e165d 100644
--- a/Lib/defcon/test/objects/test_dataSet.py
+++ b/Lib/defcon/test/objects/test_dataSet.py
@@ -1,9 +1,7 @@
 import unittest
 import os
 import shutil
-import fs
-import fs.copy
-import fs.path
+import fontTools.misc.filesystem as fs
 from defcon import Font
 from defcon.test.testTools import (
     getTestFontPath, getTestFontCopyPath, makeTestFontCopy,
diff --git a/Lib/defcon/test/objects/test_font.py b/Lib/defcon/test/objects/test_font.py
index 805e6b8..f7c9fce 100644
--- a/Lib/defcon/test/objects/test_font.py
+++ b/Lib/defcon/test/objects/test_font.py
@@ -3,9 +3,7 @@ import os
 import glob
 import tempfile
 import shutil
-import fs
-import fs.copy
-import fs.path
+import fontTools.misc.filesystem as fs
 from defcon import Font, Glyph, LayerSet, Guideline
 from defcon.errors import DefconError
 from defcon.tools.notifications import NotificationCenter
diff --git a/Lib/defcon/test/objects/test_imageSet.py b/Lib/defcon/test/objects/test_imageSet.py
index eaa93f2..bce80e1 100644
--- a/Lib/defcon/test/objects/test_imageSet.py
+++ b/Lib/defcon/test/objects/test_imageSet.py
@@ -1,9 +1,7 @@
 from __future__ import unicode_literals
 import unittest
 import os
-import fs
-import fs.copy
-import fs.path
+import fontTools.misc.filesystem as fs
 from fontTools.ufoLib import UFOReader
 from defcon import Font
 from defcon.objects.imageSet import fileNameValidator
diff --git a/Lib/defcon/test/objects/test_layer.py b/Lib/defcon/test/objects/test_layer.py
index aa3b25e..b8b4e0a 100644
--- a/Lib/defcon/test/objects/test_layer.py
+++ b/Lib/defcon/test/objects/test_layer.py
@@ -1,9 +1,7 @@
 import unittest
 import glob
 import os
-import fs
-import fs.copy
-import fs.path
+import fontTools.misc.filesystem as fs
 from fontTools.ufoLib import UFOReader, UFOFileStructure
 from defcon import Font, Glyph, Color, Component, Anchor, Guideline
 from defcon.test.testTools import (
diff --git a/Lib/defcon/test/objects/test_layerSet.py b/Lib/defcon/test/objects/test_layerSet.py
index c3016f1..9c4158d 100644
--- a/Lib/defcon/test/objects/test_layerSet.py
+++ b/Lib/defcon/test/objects/test_layerSet.py
@@ -1,8 +1,7 @@
 import unittest
 import os
 import shutil
-import fs
-import fs.copy
+import fontTools.misc.filesystem as fs
 from fontTools.ufoLib import UFOReader
 from defcon import Font
 from defcon.test.testTools import (
diff --git a/Lib/defcon/test/testTools.py b/Lib/defcon/test/testTools.py
index f88066c..667deab 100644
--- a/Lib/defcon/test/testTools.py
+++ b/Lib/defcon/test/testTools.py
@@ -3,10 +3,8 @@ import os
 import shutil
 from pkg_resources import resource_filename
 import zipfile
-import fs.osfs
-import fs.tempfs
-import fs.zipfs
-import fs.copy
+import fontTools.misc.filesystem as fs
+
 
 TESTDATA_DIR = resource_filename("defcon.test", 'testdata')
 

@benkiel benkiel merged commit e185b9a into master Jul 15, 2025
8 checks passed
@benkiel benkiel deleted the ft-fs branch July 15, 2025 16:55
@benkiel
Copy link
Member

benkiel commented Jul 15, 2025

Thanks for this!

@benkiel
Copy link
Member

benkiel commented Jul 15, 2025

@anthrotype can you ping when that change lands in fontTools with either a note or a pr for the change in import? Once we do that I'll push a new defcon release pinned to the new fontTools version.

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.

4 participants