spyder-ide / qtawesome

Iconic fonts in PyQt and PySide applications
https://qtawesome.readthedocs.io/en/latest/index.html
MIT License
796 stars 105 forks source link

FileNotFoundError on fontawesome4-webfont-4.7.ttf #264

Open wedgef5 opened 3 weeks ago

wedgef5 commented 3 weeks ago

I have a PySide6 application using QtAwesome which has worked fine on every machine I have installed it on up until now. On this new machine, the application fails to start with a FileNotFoundError on fontawesome4-webfont-4.7.ttf. I have created a small test application, which exhibits the same problem...

import sys
import qtawesome as qta
from PySide6.QtWidgets import (QApplication, QWidget, QGridLayout,
                               QToolButton, QLabel)

app = QApplication(sys.argv)

window = QWidget()
layout = QGridLayout(window)
names = ['fa5s.grip-horizontal', 'fa5s.file-export', 'fa5s.file-import']
for i, name in enumerate(names):
    qicon = qta.icon(name, scale_factor=1.3)
    btn = QToolButton()
    btn.setIcon(qicon)
    btn.setIconSize(QSize(32, 32))
    layout.addWidget(btn, i, 0)
    layout.addWidget(QLabel(name), i, 1)
window.show()

sys.exit(app.exec_())

The error I get is this...

Traceback (most recent call last):
  File "C:\...\pydev\qta_test\qta_test.py", line 12, in <module>
    qicon = qta.icon(name, scale_factor=1.3)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\...\pydev\qta_test\.venv\Lib\site-packages\qtawesome\__init__.py", line 234, in icon
    return _instance().icon(*names, **kwargs)
           ^^^^^^^^^^^
  File "C:\...\pydev\qta_test\.venv\Lib\site-packages\qtawesome\__init__.py", line 130, in _instance
    _resource['iconic'] = IconicFont(*_BUNDLED_FONTS)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\...\pydev\qta_test\.venv\Lib\site-packages\qtawesome\iconic_font.py", line 337, in __init__
    self.load_font(*fargs)
  File "C:\...\pydev\qta_test\.venv\Lib\site-packages\qtawesome\iconic_font.py", line 377, in load_font
    with open(os.path.join(directory, ttf_filename), 'rb') as font_data:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'C:\\...\\AppData\\Local\\Microsoft\\Windows\\Fonts\\fontawesome4-webfont-4.7.ttf'

I'm using a venv, which works on every other machine I've installed on. The fontawesome4-webfont-4.7.ttf file is not present on any of the machines in the AppData path in the traceback. It IS in .venv\Lib\site-packages\qtawesome\fonts on every machine, including the one on which the error is occurring.

This is on Windows 11 and Python 3.12.5 installed from the python.org installer.

wedgef5 commented 3 weeks ago

Update...

The virtual environment doesn't matter. The same error occurs with PySide6 and QtAwesome installed in the base Python's site-packages and the venv deactivated.

ccordoba12 commented 3 weeks ago

Hey @wedgef5, thanks for reporting. Do you have permissions to write to this directory?

C:\\...\\AppData\\Local\\Microsoft\\Windows\\Fonts\\
wedgef5 commented 3 weeks ago

@ccordoba12 Yes. It is within my home directory. I also tried doing the entire install from an elevated CMD window, and it made no difference. None of the machines that I have installed on (including all of those that are working correctly) have the fonts in that path.

wedgef5 commented 3 weeks ago

One other factor worth noting: the machine where I'm having this problem is my work computer, and it is controlled by group policy from above. That said, I typically have great freedom within my own home directory and I do have admin access on the local machine. I have checked the "trusted fonts" setting as noted in #167 but that is not enabled on my machine. I do not know of any other setting that would cause the fonts to not be read from site-packages\qtawesome\fonts.

wedgef5 commented 4 days ago

I have determined that this issue is being caused by the Windows "untrusted font blocking" policy. In my case, however, it appears to be slightly different than what was addressed in #167. The Group Policy on my machine seems to not allow ANY fonts to be installed at all. I have some administrator access on my local machine, and I still can't do it. Even after copying the ttf files to %SystemRoot%\Fonts (which is supposed to be the location to put "trusted" fonts), the Install button in File Explorer is grayed out. If I try to right-click, Install, I get a message about the file not being a "valid" font file. My Windows Event Viewer is full of messages about the font installation being blocked.

I think the reason I was getting the FileNotFoundException is due to this section of iconic_font.py in IconicFont._install_fonts()

                if os.path.splitext(filename)[-1] == '.ttf':
                    # Load the font in the current session
                    if not gdi32.AddFontResourceW(dst_path):
                        try:
                            os.remove(dst_path)
                        except OSError:
                            # Possible permission error when trying to remove
                            # a font which potentially is already in use
                            # See spyder-ide/qtawesome#236
                            continue

When gdi32.AddFontResourceW() fails (due to the blocking policy), it returns zero. That causes the file to be removed from the user Font directory, then load_font() tries to open it.

Should a separate issue be opened to more gracefully handle this case of font-blocking or perhaps just rename this issue?