<h3 dir="auto">Bug summary</h3>
<p dir="auto">Direct access to top level modules of <code class="notranslate">matplotlib</code> raises <code class="notranslate">AttributeError</code> for most of the documented top-level modules.  This was discovered when attempting to refer to module contents for type-hints that are evaluated when a function is defined.  This occurs reproducibly where no previous matplotlib module imports have occurred prior to evaluation of the code referencing a module namespaced by <code class="notranslate">matplotlib</code></p>
<h3 dir="auto">Code for reproduction</h3>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import matplotlib

def do_something_with_figure(fig: matplotlib.figure.Figure):
    pass

print('doing some actual runtime code...')"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">matplotlib</span>

<span class="pl-k">def</span> <span class="pl-en">do_something_with_figure</span>(<span class="pl-s1">fig</span>: <span class="pl-s1">matplotlib</span>.<span class="pl-s1">figure</span>.<span class="pl-v">Figure</span>):
    <span class="pl-k">pass</span>

<span class="pl-en">print</span>(<span class="pl-s">'doing some actual runtime code...'</span>)</pre></div>
<h3 dir="auto">Actual outcome</h3>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Traceback (most recent call last):
  File &quot;typehint-mpl.py&quot;, line 3, in &lt;module&gt;
    def do_something_with_figure(fig: matplotlib.figure.Figure):
  File &quot;/usr/local/lib/python3.8/site-packages/matplotlib/_api/__init__.py&quot;, line 226, in __getattr__
    raise AttributeError(
AttributeError: module 'matplotlib' has no attribute 'figure'"><pre class="notranslate"><code class="notranslate">Traceback (most recent call last):
  File "typehint-mpl.py", line 3, in &lt;module&gt;
    def do_something_with_figure(fig: matplotlib.figure.Figure):
  File "/usr/local/lib/python3.8/site-packages/matplotlib/_api/__init__.py", line 226, in __getattr__
    raise AttributeError(
AttributeError: module 'matplotlib' has no attribute 'figure'
</code></pre></div>
<h3 dir="auto">Expected outcome</h3>
<p dir="auto">For this example script, we would obviously expect to reach the <code class="notranslate">print()</code> statement.</p>
<h3 dir="auto">Additional information</h3>
<p dir="auto">This appears to be a general issue with most top-level modules.  The following attempts to access all top-level modules named in the current <code class="notranslate">help(matplotlib)</code>:</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="$ cat test_modules.py 
import matplotlib


MODULES = ['axes', 'figure', 'artist', 'lines', 'patches', 'text', 'image', 'collections',
           'colors', 'cm', 'ticker', 'backends']

for module in MODULES:
    try:
        _ = getattr(matplotlib, module)
        print(f'got {module}')
    except AttributeError:
        print(f'failed to access {module}')
$ python test_modules.py
failed to access axes
failed to access figure
failed to access artist
failed to access lines
failed to access patches
failed to access text
failed to access image
failed to access collections
got colors
got cm
got ticker
failed to access backends"><pre class="notranslate">$ cat test_modules.py 
import matplotlib


MODULES = [<span class="pl-s"><span class="pl-pds">'</span>axes<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>figure<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>artist<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>lines<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>patches<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>text<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>image<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>collections<span class="pl-pds">'</span></span>,
           <span class="pl-s"><span class="pl-pds">'</span>colors<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>cm<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>ticker<span class="pl-pds">'</span></span>, <span class="pl-s"><span class="pl-pds">'</span>backends<span class="pl-pds">'</span></span>]

<span class="pl-k">for</span> <span class="pl-smi">module</span> <span class="pl-k">in</span> MODULES:
    try:
        _ = getattr(matplotlib, module)
        print(f<span class="pl-s"><span class="pl-pds">'</span>got {module}<span class="pl-pds">'</span></span>)
    except AttributeError:
        print(f<span class="pl-s"><span class="pl-pds">'</span>failed to access {module}<span class="pl-pds">'</span></span>)
$ python test_modules.py
failed to access axes
failed to access figure
failed to access artist
failed to access lines
failed to access patches
failed to access text
failed to access image
failed to access collections
got colors
got cm
got ticker
failed to access backends</pre></div>
<p dir="auto">Note - I think this issue is due to some sort of lazy-loading behaviour, there are various ways by which the <code class="notranslate">AttributeError</code> can be avoided.  If previous imports such as <code class="notranslate">import matplotlb.pyplot as plt</code> have already occurred before references to <code class="notranslate">matplotlib.xxxx</code> occur this appears ok, and also, while investigating interactively, it appears that simply showing the <code class="notranslate">help()</code> in the python shell unblocks this access:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Python 3.8.16 (default, May 23 2023, 14:26:40) 
[GCC 10.2.1 20210110] on linux
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
&gt;&gt;&gt; import matplotlib
&gt;&gt;&gt; matplotlib.figure
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
  File &quot;/usr/local/lib/python3.8/site-packages/matplotlib/_api/__init__.py&quot;, line 226, in __getattr__
    raise AttributeError(
AttributeError: module 'matplotlib' has no attribute 'figure'
&gt;&gt;&gt; help(matplotlib)
# q to leave help
&gt;&gt;&gt; matplotlib.figure
&lt;module 'matplotlib.figure' from '/usr/local/lib/python3.8/site-packages/matplotlib/figure.py'&gt;"><pre class="notranslate"><code class="notranslate">Python 3.8.16 (default, May 23 2023, 14:26:40) 
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
&gt;&gt;&gt; import matplotlib
&gt;&gt;&gt; matplotlib.figure
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
  File "/usr/local/lib/python3.8/site-packages/matplotlib/_api/__init__.py", line 226, in __getattr__
    raise AttributeError(
AttributeError: module 'matplotlib' has no attribute 'figure'
&gt;&gt;&gt; help(matplotlib)
# q to leave help
&gt;&gt;&gt; matplotlib.figure
&lt;module 'matplotlib.figure' from '/usr/local/lib/python3.8/site-packages/matplotlib/figure.py'&gt;
</code></pre></div>
<p dir="auto">The above interactive behaviour can be replicated by invoking <code class="notranslate">pydoc.render_doc()</code>; the following version of the code example gives no error:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import pydoc
import matplotlib

_ = pydoc.render_doc(matplotlib)

def do_something_with_figure(fig: matplotlib.figure.Figure):
    pass"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">pydoc</span>
<span class="pl-k">import</span> <span class="pl-s1">matplotlib</span>

<span class="pl-s1">_</span> <span class="pl-c1">=</span> <span class="pl-s1">pydoc</span>.<span class="pl-en">render_doc</span>(<span class="pl-s1">matplotlib</span>)

<span class="pl-k">def</span> <span class="pl-en">do_something_with_figure</span>(<span class="pl-s1">fig</span>: <span class="pl-s1">matplotlib</span>.<span class="pl-s1">figure</span>.<span class="pl-v">Figure</span>):
    <span class="pl-k">pass</span></pre></div>
<p dir="auto">All examples in this report are with matplotlib installed in python3.8 bullseye docker image via pip as follows:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="FROM python:3.8-bullseye

RUN pip install --upgrade pip \
    &amp;&amp; pip install matplotlib==3.7.1

ENTRYPOINT [&quot;python&quot;]"><pre lang="docker" class="notranslate"><code class="notranslate">FROM python:3.8-bullseye

RUN pip install --upgrade pip \
    &amp;&amp; pip install matplotlib==3.7.1

ENTRYPOINT ["python"]
</code></pre></div>
<h3 dir="auto">Operating system</h3>
<p dir="auto">Observed on Debian buster &amp; bullseye and Ubuntu 18.04, 20.04 &amp; 22.04</p>
<h3 dir="auto">Matplotlib Version</h3>
<p dir="auto">Various.  Code examples using 3.7.1, with behaviour definitely occurring with 3.5.2, 3.6.2 &amp; 3.6.3</p>
<h3 dir="auto">Matplotlib Backend</h3>
<p dir="auto">'agg'</p>
<h3 dir="auto">Python version</h3>
<p dir="auto">Various 3.8.x, 3.9.x</p>
<h3 dir="auto">Jupyter version</h3>
<p dir="auto"><em>No response</em></p>
<h3 dir="auto">Installation</h3>
<p dir="auto">pip</p>
<p dir="auto">I get AttributeError: module 'matplotlib' has no attribute 'dates', when trying to access date functions.<br>
eg. mpl.dates.num2date(date + epoch_adjustment)</p>
<p dir="auto">version: matplotlib-3.5.1-cp39-cp39-macosx_11_0_arm64.whl</p>