From 51b1ae8e58773a6a804af814e3b8ae2321b0ccde Mon Sep 17 00:00:00 2001 From: Colin Ophus Date: Sat, 1 Aug 2026 11:42:41 -0500 Subject: [PATCH] Fix pyparsing deprecation flood without touching matplotlib Reverts the matplotlib >= 3.11 requirement: hosted notebook runtimes (Colab) preimport matplotlib at kernel start, so a mid-session pip upgrade leaves a broken half-old, half-new install (new mpl_toolkits.axes_grid1 loaded lazily against the old in-memory matplotlib._api). Instead, rebind pyparsing's deprecated camelCase compatibility aliases (parseString / resetCache, including the parseAll argument) to call the snake_case API directly with the renamed arguments. matplotlib < 3.11 mathtext calls those aliases once per rendered math label, which floods plotting output under pyparsing >= 3.3; with the rebind the deprecated code paths are never executed, in any session, with no install changes. Verified the rebound aliases give identical parse results and exceptions, emit no warnings, and are skipped on matplotlib >= 3.11. Co-Authored-By: Claude Fable 5 --- py4DSTEM/__init__.py | 23 +++++++++++++++++++++++ setup.py | 6 +----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/py4DSTEM/__init__.py b/py4DSTEM/__init__.py index e26f24c78..e683632b7 100644 --- a/py4DSTEM/__init__.py +++ b/py4DSTEM/__init__.py @@ -1,6 +1,29 @@ from py4DSTEM.version import __version__ from emdfile import tqdmnd +# matplotlib < 3.11 mathtext calls pyparsing's deprecated camelCase API +# (parseString / parseAll / resetCache) once per rendered math label, which +# floods plotting output with deprecation messages under pyparsing >= 3.3. +# Rebind those compatibility aliases to call the snake_case API directly with +# the renamed arguments, so the deprecated code paths are never executed. +# Upgrading matplotlib instead is not an option in hosted notebooks (Colab +# preimports matplotlib, and a mid-session upgrade leaves a broken half-old, +# half-new install). Skipped entirely on matplotlib >= 3.11. +import matplotlib as _matplotlib +import pyparsing as _pyparsing + +if getattr(_matplotlib, "__version_info__", (99,)) < (3, 11) and hasattr( + _pyparsing.ParserElement, "parse_string" +): + + def _parse_string_compat(self, instring, parseAll=False, *, parse_all=None): + return self.parse_string( + instring, parse_all=parseAll if parse_all is None else parse_all + ) + + _pyparsing.ParserElement.parseString = _parse_string_compat + _pyparsing.ParserElement.resetCache = classmethod(lambda cls: cls.reset_cache()) + from importlib.metadata import packages_distributions is_package_lite = "py4DSTEM-lite" in packages_distributions()["py4DSTEM"] diff --git a/setup.py b/setup.py index 242f332f2..a220b9cf5 100644 --- a/setup.py +++ b/setup.py @@ -28,11 +28,7 @@ "h5py >= 3.2.0", "hdf5plugin >= 4.1.3", "ncempy >= 1.8.1", - # matplotlib < 3.11 calls pyparsing's deprecated camelCase API from - # mathtext, which floods plotting output with deprecation warnings - # under pyparsing >= 3.3; require 3.11 wherever python allows it - "matplotlib >= 3.2.2; python_version < '3.11'", - "matplotlib >= 3.11; python_version >= '3.11'", + "matplotlib >= 3.2.2", "scikit-image >= 0.17.2", "scikit-learn >= 0.23.2", "scikit-optimize >= 0.9.0",