Run CI for Python 3.14 free-threading (#20029)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 84f12df..83cf22a 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -59,6 +59,12 @@
           toxenv: py
           tox_extra_args: "-n 4"
           test_mypyc: true
+        - name: Test suite with py314t-ubuntu, mypyc-compiled
+          python: '3.14t'
+          os: ubuntu-24.04-arm
+          toxenv: py
+          tox_extra_args: "-n 4"
+          test_mypyc: true
         - name: Test suite with py314-windows-64
           python: '3.14'
           os: windows-latest
diff --git a/mypy/report.py b/mypy/report.py
index 2667c70..ce6a59a 100644
--- a/mypy/report.py
+++ b/mypy/report.py
@@ -8,6 +8,7 @@
 import os
 import shutil
 import sys
+import sysconfig
 import time
 import tokenize
 from abc import ABCMeta, abstractmethod
@@ -25,9 +26,13 @@
 from mypy.version import __version__
 
 try:
-    from lxml import etree  # type: ignore[import-untyped]
+    if sys.version_info >= (3, 14) and bool(sysconfig.get_config_var("Py_GIL_DISABLED")):
+        # lxml doesn't support free-threading yet
+        LXML_INSTALLED = False
+    else:
+        from lxml import etree  # type: ignore[import-untyped]
 
-    LXML_INSTALLED = True
+        LXML_INSTALLED = True
 except ImportError:
     LXML_INSTALLED = False
 
diff --git a/mypy/test/testcheck.py b/mypy/test/testcheck.py
index a884139..96be1a0 100644
--- a/mypy/test/testcheck.py
+++ b/mypy/test/testcheck.py
@@ -5,6 +5,7 @@
 import os
 import re
 import sys
+import sysconfig
 import tempfile
 from pathlib import Path
 
@@ -27,7 +28,11 @@
 from mypy.test.update_data import update_testcase_output
 
 try:
-    import lxml  # type: ignore[import-untyped]
+    if sys.version_info >= (3, 14) and bool(sysconfig.get_config_var("Py_GIL_DISABLED")):
+        # lxml doesn't support free-threading yet
+        lxml = None
+    else:
+        import lxml  # type: ignore[import-untyped]
 except ImportError:
     lxml = None
 
diff --git a/mypy/test/testcmdline.py b/mypy/test/testcmdline.py
index 11d2290..909ea13 100644
--- a/mypy/test/testcmdline.py
+++ b/mypy/test/testcmdline.py
@@ -10,6 +10,7 @@
 import re
 import subprocess
 import sys
+import sysconfig
 
 from mypy.test.config import PREFIX, test_temp_dir
 from mypy.test.data import DataDrivenTestCase, DataSuite
@@ -20,7 +21,11 @@
 )
 
 try:
-    import lxml  # type: ignore[import-untyped]
+    if sys.version_info >= (3, 14) and bool(sysconfig.get_config_var("Py_GIL_DISABLED")):
+        # lxml doesn't support free-threading yet
+        lxml = None
+    else:
+        import lxml  # type: ignore[import-untyped]
 except ImportError:
     lxml = None
 
diff --git a/mypy/test/testreports.py b/mypy/test/testreports.py
index f638756..a971f29 100644
--- a/mypy/test/testreports.py
+++ b/mypy/test/testreports.py
@@ -2,13 +2,19 @@
 
 from __future__ import annotations
 
+import sys
+import sysconfig
 import textwrap
 
 from mypy.report import CoberturaPackage, get_line_rate
 from mypy.test.helpers import Suite, assert_equal
 
 try:
-    import lxml  # type: ignore[import-untyped]
+    if sys.version_info >= (3, 14) and bool(sysconfig.get_config_var("Py_GIL_DISABLED")):
+        # lxml doesn't support free-threading yet
+        lxml = None
+    else:
+        import lxml  # type: ignore[import-untyped]
 except ImportError:
     lxml = None