FIX: stubs and ConfigSource doc#367
Conversation
line_profiler/autoprofile/cli_utils.pyi
ActionLike
Added parametrization because `add_argument()` fails type check
otherwise
short_string_path()
Changed `pathlib.PurePath` in parameter annotation to
`os.PathLike[str]`
line_profiler/line_profiler.pyi
get_column_widths(), LineProfiler.print_stats()
show_func(), show_text()
Changed `pathlib.PurePath` in parameter annotation to
`os.PathLike[str]`
LineProfiler.__call__()
Added more specific overloads to ensure that parametrization of
parametrizable types (e.g. `staticmethod[PS, T]`) are inherited
by the return value
line_profiler/profiler_mixin.pyi::ByCountProfilerMixin
wrap_callable()
Added more specific overloads to ensure that parametrization of
parametrizable types (e.g. `staticmethod[PS, T]`) are inherited
by the return value
wrap_classmethod(), wrap_staticmethod(), wrap_partialmethod()
wrap_partial(), wrap_cached_property()
Added type parameters to the argument and the return type
line_profiler/scoping_policy.pyi::ScopingPolicy.EXACT
Added missing enumeration item
line_profiler/toml_config.pyi::ConfigSource
path
Added missing field
source
Removed nonexistent field
|
Apropos, I appreciate the rationale behind separating the type annotations into their own stub files:
However, this does prevent |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #367 +/- ##
==========================================
+ Coverage 87.56% 88.18% +0.61%
==========================================
Files 18 20 +2
Lines 1641 1862 +221
Branches 348 401 +53
==========================================
+ Hits 1437 1642 +205
- Misses 149 160 +11
- Partials 55 60 +5
... and 1 file with indirect coverage changes Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
|
LGTM. Would running mypy on an installed wheel help in the CI? Strange that it picks up stubs in non-editable mode, but not in editable mode. |
|
Upon closer inspection, this seems to be two separate problems and they are deeper than I suspected: What's wrong with editable installs?
The problem was that if ... unless we're willing to write and maintain a Is our code type-checked at all?
Unfortunately no. The problem seems to be that if a stub file exists,
Hence even with Trying to explicitly include both the (py3.13) $ find line_profiler \( -name '*.py' -o -name '*.pyi' \) | xargs mypy --check-untyped
line_profiler/line_profiler_utils.py: error: Duplicate module named "line_profiler.line_profiler_utils" (also at "line_profiler/line_profiler_utils.pyi")
line_profiler/line_profiler_utils.py: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#mapping-file-paths-to-modules for more info
line_profiler/line_profiler_utils.py: note: Common resolutions include: a) using `--exclude` to avoid checking one of them, b) adding `__init__.py` somewhere, c) using `--explicit-package-bases` or adjusting MYPYPATH
Found 1 error in 1 file (errors prevented further checking)The only way out seem to be doing something like find line_profiler -name '*.py' | xargs mypy --check-untypedbut that obviously ignores information present in the |

This PR addresses the following issues with recent PRs. (Note that there is no actual behavior change on the code-side).
Typing bugs
line_profiler.cli_utils.add_argument(ArgumentParser(...), ...)actually fails type check.line_profiler.toml_config.ConfigSourceshould have a.pathfield instead of a.sourcefield.line_profiler.scoping_policy.ScopingPolicyis missing an.EXACTitem.These typing bugs went under our nose because we only do stubs, and thus
mypydon't really look into how we're using any of these. Butmypyflared up the moment I installed theline_profilerin a non-editable way in another project, which got me investigating... and here we are. This PR remedies the above bugs.While we're at it, I also updated the stubs for
line_profiler.profiler_mixin.ByCountProfilerMixin.wrap_*()andline_profiler.line_profiler.LineProfiler.__call__()so that we get better parametrizations for the param specs and return values (e.g.p: partial[int] = ...; p_profiled = reveal_type(profile(p))givespartial[int]instead ofpartial[Any]).Lacking docs
Shortly after finishing #335 I realized that we never explained whence the config file is looked up (i.e. the current directory's and its ancestors'
line_profiler.tomlandpyproject.toml) in the online docs, because neitherline_profiler.toml_config.find_and_read_config_file()nor.TARGETSis in.__all__, and they are thus omitted from the built doc pages. The PR thus rewrites the docstring forline_profiler.toml_config.ConfigSource.from_config()to (1) be more clear, and (2) document the aforementioned lookup targets and mechanism.