Fix: fix: handle None module in module_available() to avoid TypeError

Fixed pydata/xarray#11344 — 5 line bug-fix adding explicit None guard to module_available().

The Bug

Repo: pydata/xarray Issue: #11344 Status: PR-submitted PR: https://github.com/pydata/xarray/pull/11448

Description: When module_available() is called with None — for example, through a third-party plugin import chain — importlib.util.find_spec(None) raises TypeError instead of gracefully returning False.

Fix scope: 5 lines changed in xarray/namedarray/utils.py

Root Cause

The module_available() function uses importlib.util.find_spec() to check whether a Python module is installed. The function signature previously required module: str, meaning callers should always pass a string. However, in practice, some third-party code paths could pass None — for example, when a plugin’s configuration uses optional dependencies that might not resolve during import.

When importlib.util.find_spec(None) is called, it raises TypeError: the 'package' argument is required to perform a relative import for ''. The error message is confusing because the term “None” is never mentioned, making it hard to trace back to the null input.

Impact: Low for end users, but disruptive for plugin authors and developers integrating xarray with dynamic import systems. Any third-party extension that calls module_available() with an optional module reference (which could be None when a configuration is incomplete) would crash with a TypeError instead of gracefully degrading. The fix ensures module_available(None) returns False, matching the intuitive expectation: if no module is provided, it’s not available.

The Fix

Two changes in xarray/namedarray/utils.py:

  1. Type hint update: module: strmodule: str | None to reflect the accepted input types.
  2. Early return guard: Added a None check at the top of the function body that returns False.
if module is None:
    return False

This tiny guard (5 lines with the type hint change) prevents the confusing TypeError from propagating and matches how similar functions in the Python ecosystem handle null input — for example, many find_spec() wrappers in other projects use this exact pattern.

Pattern & Takeaways

Pattern: Functions that delegate to stdlib functions with strict type expectations (find_spec requires str) should guard against None input when there’s any possibility it could arrive through user-facing or plugin-facing APIs. The guard is cheap (one comparison) and prevents an opaque TypeError from masking the real issue.

Key insight: Type hints don’t enforce runtime behavior. Even with module: str, callers can pass None. The safest approach is to add an explicit guard at API boundaries, especially for utility functions that may be called from dynamic or plugin-based code paths. The cost of a single if module is None: return False is negligible, but it saves debugging time.

Transfer Potential

Highmodule_available()-style functions exist in every Python project that does optional dependency checking. The pattern of guarding None for functions wrapping importlib.util.find_spec() is directly applicable anywhere a module name string could be None at runtime.


Auto-generated from PR #11448. View all patches on GitHub.

References

[1] pydata/xarray [2] #11344 [3] https://github.com/pydata/xarray/pull/11448