On 21/07/2020 9:46 pm, Gregory P. Smith wrote:
> On Fri, Jul 17, 2020 at 8:41 AM Ned Batchelder <firstname.lastname@example.org
> <mailto:email@example.com>> wrote:
> https://www.python.org/dev/peps/pep-0626/ :)
> On 7/17/20 10:48 AM, Mark Shannon wrote:
> > Hi all,
> > I'd like to announce a new PEP.
> > It is mainly codifying that Python should do what you probably
> > thought it did :)
> > Should be uncontroversial, but all comments are welcome.
> > Cheers,
> > Mark.
> """When a frame object is created, the f_lineno will be set to the line
> at which the function or class is defined. For modules it will be set to
> Within this PEP it'd be good for us to be very pedantic. f_lineno is a
> single number. So which number is it given many class and function
> definition statements can span multiple lines.
> Is it the line containing the class or def keyword? Or is it the line
> containing the trailing :?
The line of the `def`/`class`. It wouldn't change for the current
behavior. I'll add that to the PEP.
> Q: Why can't we have the information about the entire span of lines
> rather than consider a definition to be a "line"?
Pretty much every profiler, coverage tool, and debugger ever expects
lines to be natural numbers, not ranges of numbers.
A lot of tooling would need to be changed.
> I think that question applies to later sections as well. Anywhere we
> refer to a "line", it could actually mean a span of lines. (especially
> when you consider \ continuation in situations you might not otherwise
> think could span lines)
Let's take an example:
x = (
You would want the BUILD_TUPLE instruction to have a of span lines 1 to
4 (inclusive), rather just line 1?
If you wanted to break on the BUILD_TUPLE where you tell pdb to break?
I don't see that it would add much value, but it would add a lot of
We should have the data about the range at bytecode compilation time, correct? So why not keep it? sure, most existing tooling would just use the start of the range as the line number as it always has. but some tooling could find the range useful (ex: semantic code indexing for use in display, search, editors, IDEs. Rendering lint errors more accurately instead of just claiming a single line or resorting to parsing hacks to come up with a range, etc.). The downside is that we'd be storing a second number in bytecode making it slightly larger. Though it could be stored efficiently as a prefixed delta so it'd likely average out as less than 2 bytes per line number stored. (i don't have a feeling for our current format to know if that is significant or not - if it is, maybe this idea just gets nixed)
The reason the range concept was on my mind is due to something not quite related but involving a changed idea of a line number in our current system that we recently ran into with pytype during a Python upgrade.
"""in 3.7, if a function body is a plain docstring, the line number of the RETURN_VALUE opcode corresponds to the docstring, whereas in 3.6 it corresponds to the function definition.""" (Thanks, Martin & Rebecca!)
"""docstring instead of pass."""
so the location of what was originally an end of line `# pytype: disable=bad-return-type` comment (to work around an issue not relevant here) turned awkward and version dependent. pytype is bytecode based, thus that is where its line numbers come from. metadata comments in source can only be tied to bytecode via line numbers. making end of line directives occasionally hard to match up.
When there is no return statement, this opcode still exists. what line number does it belong to? 3.6's answer made sense to me. 3.7's seems wrong - a docstring isn't responsible for a return opcode. I didn't check what 3.8 and 3.9 do. An alternate answer after this PEP is that it wouldn't have a line number when there is no return statement (pedantically correct, I approve! #win).