You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
bug: strict = true is incompatible with per-module configuration #11401
That is, I want strict mode in my source code but not my tests.
Then I run this using mypy .
Expected Behavior
I expect to get an error for my source code but not my tests:
my_module/__init__.py:1: error: Function is missing a return type annotation
my_module/__init__.py:1: note: Use "-> None" if function does not return a value
Actual Behavior
I get an error for both my source code and tests.
It seems like strict = False in the per module section is ignored.
tests/__init__.py:1: error: Function is missing a return type annotation
tests/__init__.py:1: note: Use "-> None" if function does not return a value
my_module/__init__.py:1: error: Function is missing a return type annotation
my_module/__init__.py:1: note: Use "-> None" if function does not return a value
If I add an explicit allow_untyped_defs = True to the mypy-tests.* section:
That seems to be processed fine (I now get no errors for my tests but still get errors for my source).
So I believe the config file is valid, mypy is picking up that the options only apply to tests.*.
changed the title [-]strict is incompatible with per-module configuration[/-][+]bug: strict = true is incompatible with per-module configuration[/+]on Oct 28, 2021
I tried inserting all the flags that mypy --help suggested would be turned on by strict by hand, and found that warn_redundant_casts and warn_unused_configs are global, which may be the source of the issue.
Possible solutions:
update the documentation to specify that strict is a global-only option
change the behaviour of strict when placed in a per-module configuration block
extend those two flags so they can be placed in a per-module configuration block
I have absolutely no idea how hard either of those last two options might be, so updating the docs seems like a good option.
This also presents an issue when type-checking tests where looser type checking might be desirable on account of dependencies lacking types... For example, those which make use of decorators (e.g. @pytest.fixture):
tests/conftest.py:36: error: Untyped decorator makes function "my_fixture" untyped [misc]
Throwing this into consideration, although this isn't a blocking issue for me personally as I can just be (somewhat) more specific (e.g. disable_error_code = ["misc"]).
Throwing this into consideration, although this isn't a blocking issue for me personally as I can just be (somewhat) more specific (e.g. disable_error_code = ["misc"]).
That's what I ended up having to do for my main application packages I haven't gotten around to yet. The namespace package is configured to be strict=True and then there are dozen sub-packages where I have disable_error_code listing about 9 or so error codes... 🤷
The workaround for the "slowly migrating untyped code" use case is to expand the --strict options and apply them per-module, with the exception of the two that must be global:
[mypy]
# must be global, likely pass when migrating untyped code
warn_unused_configs = True
warn_redundant_casts = True
[mypy-app.foo.*,app.bar.*]
# Turn on strict type checking for select modules
#
# The intention is to migrate all modules over time; Add modules to this section as you fix them.
#
# These are all "mypy --strict" options listed in
# https://mypy.readthedocs.io/en/stable/existing_code.html#introduce-stricter-options
# with the exception of warn_redundant_casts and warn_unused_configs,
# which are global
# Start off with these
# warn_unused_configs = True <-- can only be set globally
# warn_redundant_casts = True <-- can only be set globally
warn_unused_ignores = True
# Getting these passing should be easy
strict_equality = True
strict_concatenate = True
# Strongly recommend enabling this one as soon as you can
check_untyped_defs = True
# These shouldn't be too much additional work, but may be tricky to
# get passing if you use a lot of untyped libraries
disallow_subclassing_any = True
disallow_untyped_decorators = True
disallow_any_generics = True
# These next few are various gradations of forcing use of type annotations
disallow_untyped_calls = True
disallow_incomplete_defs = True
disallow_untyped_defs = True
# This one isn't too hard to get passing, but return on investment is lower
no_implicit_reexport = True
# This one can be tricky to get passing if you use a lot of untyped libraries
warn_return_any = True
This is strict in app.foo, app.bar and not strict in the rest of app.
It has been 3 years ago since this issue was opened and for the maintainers who understand the code... is it really so difficult to fix this issue and not frustrate people? Because of this issue, the proper adoption and DRY solution for the code is impossible.
Either you duplicate all strict parameters like @vbraun suggested (and fingers crossed that they will not be updated, though it is stated in the docs that it is mutable without any notification).
Or you should not adopt mypy at all as a lot of packages just do not have types, or not strict and we are using these third party libraries everywhere in our code.
How to handle this situation? Probably we will go with solution provided by @vbraun , but it is not DRY and error prone in case the set of strict parameters will be updated.
It has been 3 years ago since this issue was opened and for the maintainers who understand the code... is it really so difficult to fix this issue and not frustrate people? Because of this issue, the proper adoption and DRY solution for the code is impossible.
Is there a PR?
If PRs are being ignored, then it's arguably worth pestering.
But there's no duty for anyone to add the features you want — "you've had three years to do the work I asked for" is not helpful.
Reacted by Shantanu, Brad Warren and Andrei Korshikov
+1 to @vbraun and @max-sixty : strict is just 12 non-global options. Adding 12 strings to a module configuration is not that hard (don't forget to replace strict_concatenate with extra_checks and that no_implicit_reexport = True is equivalent to implicit_reexport = False).
TBC, I still think it would be much better to have this working per-module! I was responding to the demand for work; I still think the work would make sense to do
Activity
[-]strict is incompatible with per-module configuration[/-][+]bug: strict = true is incompatible with per-module configuration[/+]alicederyn commentedon Jan 24, 2022
I tried inserting all the flags that
mypy --helpsuggested would be turned on bystrictby hand, and found thatwarn_redundant_castsandwarn_unused_configsare global, which may be the source of the issue.Possible solutions:
strictis a global-only optionstrictwhen placed in a per-module configuration blockI have absolutely no idea how hard either of those last two options might be, so updating the docs seems like a good option.
sshishov commentedon Dec 18, 2022
Same here. We tried to move slowly to
strict = truemode per module which has been "migrated" but cannot do it due to this limitationcal-pratt commentedon May 1, 2023
Any update on this? Was also hoping to use this strategy to onboard a larger project with proper type hinting.
DylanLukes commentedon May 4, 2023
This also presents an issue when type-checking tests where looser type checking might be desirable on account of dependencies lacking types... For example, those which make use of decorators (e.g.
@pytest.fixture):Throwing this into consideration, although this isn't a blocking issue for me personally as I can just be (somewhat) more specific (e.g.
disable_error_code = ["misc"]).cal-pratt commentedon May 5, 2023
That's what I ended up having to do for my main application packages I haven't gotten around to yet. The namespace package is configured to be
strict=Trueand then there are dozen sub-packages where I havedisable_error_codelisting about 9 or so error codes... 🤷vbraun commentedon Aug 2, 2023
The workaround for the "slowly migrating untyped code" use case is to expand the
--strictoptions and apply them per-module, with the exception of the two that must be global:This is strict in
app.foo,app.barand not strict in the rest ofapp.sshishov commentedon Nov 7, 2023
Hello guys,
It has been 3 years ago since this issue was opened and for the maintainers who understand the code... is it really so difficult to fix this issue and not frustrate people? Because of this issue, the proper adoption and DRY solution for the code is impossible.
Either you duplicate all strict parameters like @vbraun suggested (and fingers crossed that they will not be updated, though it is stated in the docs that it is mutable without any notification).
Or you should not adopt mypy at all as a lot of packages just do not have types, or not strict and we are using these third party libraries everywhere in our code.
How to handle this situation? Probably we will go with solution provided by @vbraun , but it is not DRY and error prone in case the set of strict parameters will be updated.
Best regards,
Sergei
max-sixty commentedon Nov 8, 2023
Is there a PR?
If PRs are being ignored, then it's arguably worth pestering.
But there's no duty for anyone to add the features you want — "you've had three years to do the work I asked for" is not helpful.
Removing the mypy check from "tests" since there seems to be no way t…
andrei-korshikov commentedon Mar 6, 2025
+1 to @vbraun and @max-sixty :
strictis just 12 non-global options. Adding 12 strings to a module configuration is not that hard (don't forget to replacestrict_concatenatewithextra_checksand thatno_implicit_reexport = Trueis equivalent toimplicit_reexport = False).max-sixty commentedon Mar 7, 2025
TBC, I still think it would be much better to have this working per-module! I was responding to the demand for work; I still think the work would make sense to do
strict=falsedoesn't work inside[[tool.mypy.overrides]]#18836 as a duplicate of this issuestrictconfiguration flag not documented #10897 as a duplicate of this issuewyattscarpenter commentedon May 12, 2025
I'm not sure about the status of it, but there is a pull request aimed towards fixing this issue: #12174