Comparing versions:

export PY38=/usr/local/pyenv/pyenv/versions/3.8.12/bin/python3.8
export PY39=/usr/local/pyenv/pyenv/versions/3.9.10/bin/python3.9
export PP38old=/usr/local/pypy/pypy3.8-v7.3.7-osx64/bin/pypy3
export PP38=/usr/local/pypy/pypy3.8-v7.3.8rc1-osx64/bin/pypy3
export PP39=/usr/local/pypy/pypy3.9-v7.3.8rc1-osx64/bin/pypy3

$ for py in $PY38 $PY39 $PP38old $PP38 $PP39; do $py -m coverage run --debug=pybehave igor.py; done 2>&1 | grep trace
            trace_decorated_def: True
     trace_decorator_line_again: False
            trace_decorated_def: True
     trace_decorator_line_again: False
            trace_decorated_def: False
     trace_decorator_line_again: False
            trace_decorated_def: False
     trace_decorator_line_again: False
            trace_decorated_def: False
     trace_decorator_line_again: False

# t466a_ast.py:
    import ast
    import sys

    def find_function(node, name):
        if node.__class__.__name__ == "FunctionDef" and node.name == name:
            return node
        for node in getattr(node, "body", ()):
            fnode = find_function(node, name)
            if fnode is not None:
                return fnode

    root_node = ast.parse(open(__file__).read())
    func_node = find_function(root_node, "parse")

    print(func_node.name, func_node.lineno, func_node.end_lineno, tuple(sys.version_info), tuple(getattr(sys, "pypy_version_info", ())))

    class Parser(object):

        @classmethod
        def parse(cls):
            formats = [ 5 ]


            return None

    Parser.parse()


$ for py in $PY38 $PY39 $PP38old $PP38 $PP39; do $py t466a_ast.py; done
parse 20 24 (3, 8, 12, 'final', 0) ()
parse 20 24 (3, 9, 10, 'final', 0) ()
parse 19 -1 (3, 8, 12, 'final', 0) (7, 3, 7, 'final', 0)
parse 19 -1 (3, 8, 12, 'final', 0) (7, 3, 8, 'final', 0)
parse 20 24 (3, 9, 10, 'final', 0) (7, 3, 8, 'final', 0)


PyPy <=3.8 includes the decorator line in the FunctionDef node
PyPy >=3.9 does not include the decorator line in the node

PyPy traces the decorator line, but not the def:

$ $PP38 -m trace --trace t466a_plain.py
 --- modulename: t466a_plain, funcname: <module>
t466a_plain.py(1): class Parser(object):
 --- modulename: t466a_plain, funcname: Parser
t466a_plain.py(1): class Parser(object):
t466a_plain.py(3):     @classmethod
t466a_plain.py(10): Parser.parse()
 --- modulename: t466a_plain, funcname: parse
t466a_plain.py(5):         formats = [ 5 ]
t466a_plain.py(8):         return None

$ $PP39 -m trace --trace t466a_plain.py
 --- modulename: t466a_plain, funcname: <module>
t466a_plain.py(1): class Parser(object):
 --- modulename: t466a_plain, funcname: Parser
t466a_plain.py(1): class Parser(object):
t466a_plain.py(3):     @classmethod
t466a_plain.py(10): Parser.parse()
 --- modulename: t466a_plain, funcname: parse
t466a_plain.py(5):         formats = [ 5 ]
t466a_plain.py(8):         return None

CPython traces the decorator and the def:

$ $PY39 -m trace --trace t466a_plain.py
 --- modulename: t466a_plain, funcname: <module>
t466a_plain.py(1): class Parser(object):
 --- modulename: t466a_plain, funcname: Parser
t466a_plain.py(1): class Parser(object):
t466a_plain.py(3):     @classmethod
t466a_plain.py(4):     def parse(cls):
t466a_plain.py(10): Parser.parse()
 --- modulename: t466a_plain, funcname: parse
t466a_plain.py(5):         formats = [ 5 ]
t466a_plain.py(8):         return None
