Clarification for typeshed's definition of `types.ModuleType` which seems to differ from Python docs description

The definition of types.ModuleType in the docs seems to indicate that the __spec__ property is always expected to be an instance of importlib.machinery.ModuleSpec.

However, typeshed allows it to be None.

I was curious about what is the reationale behind making it optional in typeshed.
Does anyone knows the reason for that?

It’s had that type since 2016, according to git blame: Add stubs for importlib.machinery (#323) · python/typeshed@43c3406 · GitHub.

There’s no discussion on the PR from 8 years ago that would let us know why it was marked as optional: Add stubs for importlib.machinery by brettcannon · Pull Request #323 · python/typeshed · GitHub.

The attribute is initialized to None when a module object is first created: cpython/Objects/moduleobject.c at d8cd0fa4e347f460d0f3277e2392504e61ed087d · python/cpython · GitHub.

You can see this if you manually created a module object:

>>> print(types.ModuleType("x").__spec__)
None

I believe importlib should always set the __spec__ attribute to a non-None value for modules that are imported normally.

1 Like

I see! Thank you!

__main__.__spec__ can also be None