Open jaraco opened 2 months ago
This should be a opt in, not everyone is implementing the dunder main check
So dunder main submodules are actually scripts
Personally I recommend to not implement any logic in them besides import and calling main
FWIW, I'm also of the opinion that __main__.py
should only import things and act as an entry-point. Just like console_scripts
. And the actual implementation would be in private modules.
I'd still like pytest to catch a syntax error in the file:
if __name__ == '__main__'
run()
or a coding error in the entry point:
if __name__ == __main__:
run()
Even if all this file does is act as an entry point, it's worthwhile to examine it. Doctests provides this functionality.
Consider packages where the primary purpose is the command, it's a little awkward to ask users to create a separate module for a short run script:
# cli.py
import sys
def run(*args=sys.argv[1:]):
print("hello world")
# __main__.py
from .cli import run
if __name__ == '__main__':
run()
That's a lot of boilerplate for a hello world example and a layer of indirection I'd like not to enforce on every application. While I agree it's good practice, even best practice, to move most of the functionality out of the "script", it also often makes sense for there to be a non-trivial amount of logic in the script.
Consider, for example, the script jaraco.develop.add-github-secrets
. Like __main__
, it's used only as an entry point. Similar to __main__
, it's not meant to be imported except as a script. Yet, there are still concerns in that script that I don't feel like exporting elsewhere; they're best associated with this particular script. Should pytest be ignoring these files too, because they could potentially contain unprotected execution? In my opinion, A test system shouldn't be imposing preferences on code organization.
I'd be satisfied by an opt-back-in if you really think that's necessary, but in my opinion, the least surprising approach is to be consistent about how modules are discovered and tested and have users opt-in to the exceptional behaviors, rather than have an inconsistency that a user can opt out of.
Prior to pytest 7, pytest would exercise doctests in
__main__
. https://github.com/pytest-dev/pytest/pull/8949 changed that expectation (and for good reason).In my use-case, I always put a
__name__ == '__main__'
check in my entry points, including__main__
and sometimes supply functions in that module that I'd like to have doctested. There are several ways I rely on doctests:Most if not all of the benefits described in In defense of doctests apply to
__main__
as much as any other package module.I've been working under the assumption that
__main__
modules were doctested in all of my projects and only today learned that they're not. I disagree that these modules should be special-cased just because some projects are unwilling to make them import-safe. Surely, pytest would consider it invalid if a user were to complain about any other module in the package failing to import because it has undesirable import-time behaviors, e.g.Yes, it's true that
__main__.py
has some special semantics, but so also does__init__.py
, but that's not justification for excluding__init__
from doctests.I note that there's a related issue https://github.com/pytest-dev/pytest/issues/11716, which proposes to give users more control to exclude things for doctests. If implemented, that approach could potentially satisfy the need for some projects to exclude
__main__
.Even prior to addressing that issue, it would have been possible for users to exclude
__main__
modules by adding it to theirpytest_collect_ignore
(or is itpytest_collectignore
; I can never remember).Can we reconsider supporting
__main__
for doctests?