{"record":{"id":"ebfb2f1370454fb8","repo":"matplotlib/matplotlib","slug":"str-ose","errorCode":null,"errorMessage":"str(_ose)","messagePattern":"str\\(_ose\\)","errorType":"exception","errorClass":"ExecutableNotFoundError","httpStatus":null,"severity":"warning","filePath":"lib/matplotlib/__init__.py","lineNumber":417,"sourceCode":"        # Execute the subprocess specified by args; capture stdout and stderr.\n        # Search for a regex match in the output; if the match succeeds, the\n        # first group of the match is the version.\n        # Return an _ExecInfo if the executable exists, and has a version of\n        # at least min_ver (if set); else, raise ExecutableNotFoundError.\n        try:\n            output = subprocess.check_output(\n                args, stderr=subprocess.STDOUT,\n                text=True, errors=\"replace\", timeout=30)\n        except subprocess.CalledProcessError as _cpe:\n            if ignore_exit_code:\n                output = _cpe.output\n            else:\n                raise ExecutableNotFoundError(str(_cpe)) from _cpe\n        except subprocess.TimeoutExpired as _te:\n            msg = f\"Timed out running {cbook._pformat_subprocess(args)}\"\n            raise ExecutableNotFoundError(msg) from _te\n        except OSError as _ose:\n            raise ExecutableNotFoundError(str(_ose)) from _ose\n        match = re.search(regex, output)\n        if match:\n            raw_version = match.group(1)\n            version = parse_version(raw_version)\n            if min_ver is not None and version < parse_version(min_ver):\n                raise ExecutableNotFoundError(\n                    f\"You have {args[0]} version {version} but the minimum \"\n                    f\"version supported by Matplotlib is {min_ver}\")\n            return _ExecInfo(args[0], raw_version, version)\n        else:\n            raise ExecutableNotFoundError(\n                f\"Failed to determine the version of {args[0]} from \"\n                f\"{' '.join(args)}, which output {output}\")\n\n    if name in os.environ.get(\"_MPLHIDEEXECUTABLES\", \"\").split(\",\"):\n        raise ExecutableNotFoundError(f\"{name} was hidden\")\n\n    if name == \"dvipng\":","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/matplotlib/matplotlib/blob/b379c1b69e012b142c0f496a52bcb30513802d72/lib/matplotlib/__init__.py#L399-L435","documentation":"Same pybind11 constructor path as hinting_factor: supplying `_kerning_factor` to matplotlib.ft2font.FT2Font (src/ft2font_wrapper.cpp:420-426) warns; the value is accepted until removal in 3.13, after which it becomes a TypeError. It also fires indirectly: font_manager._get_font forwards rcParams['text.kerning_factor'] into every FT2Font it creates (font_manager.py:1772, 1688), so setting that rcParam to a non-None int makes each newly instantiated font warn (per-thread font caching means it warns once per font). The leading underscore already marks the kwarg as internal API.","triggerScenarios":"`ft2font.FT2Font(file, _kerning_factor=123)` (any int; a float like 1.3 raises TypeError first because the C++ signature takes int, per test_ft2font.py:231-238); or `mpl.rcParams['text.kerning_factor'] = 2` followed by any text rendering that instantiates a new font.","commonSituations":"Typographic code fine-tuning letter spacing for pixel-tight labels; tools built directly on FT2Font; upgrading to 3.11 with a style file or rcParams block that still sets text.kerning_factor, causing warnings during text layout.","solutions":["Stop passing `_kerning_factor`; it is underscore-private and its public handle, the `text.kerning_factor` rcParam, is itself deprecated.","If you changed kerning globally, remove the rcParam assignment and rely on default kerning; if you must keep it temporarily, accept that each new font warns once due to caching.","Suppress the specific noise: `warnings.filterwarnings('ignore', message='The _kerning_factor parameter was deprecated')`.","Pin `matplotlib<3.11` only as a stopgap while migrating callers."],"exampleFix":"# before\nfrom matplotlib import ft2font\nfont = ft2font.FT2Font(path, _kerning_factor=2)\n\n# after\nfrom matplotlib import ft2font\nfont = ft2font.FT2Font(path)  # private kwarg dropped; use default kerning","handlingStrategy":"validation","validationCode":"import matplotlib\nfrom packaging.version import Version\nfrom matplotlib import ft2font\n\nkwargs = {}\nif Version(matplotlib.__version__) < Version(\"3.11\"):\n    kwargs[\"_kerning_factor\"] = 2\nfont = ft2font.FT2Font(path, **kwargs)  # kwarg warns in 3.11, TypeError in 3.13","typeGuard":null,"tryCatchPattern":"import warnings\nimport matplotlib as mpl\n\nwith warnings.catch_warnings(record=True) as caught:\n    warnings.simplefilter(\"always\", mpl.MatplotlibDeprecationWarning)\n    font = ft2font.FT2Font(path, _kerning_factor=2)  # last use while migrating\nassert not [w for w in caught if \"_kerning_factor\" in str(w.message)], \"still passing the deprecated kwarg\"","preventionTips":["Never call parameters with a leading underscore from user code; they are matplotlib-internal by convention.","When upgrading to 3.11+, grep code and style files for _kerning_factor and text.kerning_factor.","Run CI with MatplotlibDeprecationWarning as error to catch these before the 3.13 removal.","Rely on matplotlib's per-thread font cache: construct fonts once so any residual warning fires at most once per font."],"tags":["matplotlib","ft2font","deprecation","kerning","freetype"],"backgroundTag":"deprecated-parameter-removal","analyzedSha":"b379c1b69e012b142c0f496a52bcb30513802d72","analyzedAt":"2026-08-21T23:31:55.468Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}