Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

end_offset is ignored in subclasses of SyntaxError (3.12-only) #111609

Open
stbech opened this issue Nov 1, 2023 · 12 comments
Open

end_offset is ignored in subclasses of SyntaxError (3.12-only) #111609

stbech opened this issue Nov 1, 2023 · 12 comments
Labels
3.12 bugs and security fixes stdlib Python modules in the Lib dir topic-repl Related to the interactive shell type-bug An unexpected behavior, bug, or error

Comments

@stbech
Copy link

stbech commented Nov 1, 2023

Bug report

Bug description:

When I tried to implement a subclass of SyntaxError, the exception details ignored the end_offset-variable and just showed one caret at the position of offset.

raise SyntaxError("Error message", (None, 1, 5, 'a = sin(3)', 1, 9))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    a = sin(3)
        ^^^^
SyntaxError: Error message
class CustomSyntaxError(SyntaxError):
    pass
raise CustomSyntaxError("Error message", (None, 1, 5, 'a = sin(3)', 1, 9))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    a = sin(3)
        ^
CustomSyntaxError: Error message

CPython versions tested on:

3.11, 3.12

Operating systems tested on:

Windows

Linked PRs

@stbech stbech added the type-bug An unexpected behavior, bug, or error label Nov 1, 2023
@sobolevn
Copy link
Member

sobolevn commented Nov 1, 2023

It works correctly for me on 3.13a1:

>>> class CustomSyntaxError(SyntaxError):
...     pass
... 
>>> raise CustomSyntaxError("Error message", (None, 1, 5, 'a = sin(3)', 1, 9))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    raise CustomSyntaxError("Error message", (None, 1, 5, 'a = sin(3)', 1, 9))
  File "<string>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message

@harshitrathor3
Copy link

harshitrathor3 commented Nov 1, 2023

Also worked correctly for me on 3.10.10

raise SyntaxError("Error message", (None, 1, 5, 'a = sin(3)', 1, 9))
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    raise SyntaxError("Error message", (None, 1, 5, 'a = sin(3)', 1, 9))
  File "<string>", line 1
    a = sin(3)
        ^^^^
SyntaxError: Error message


class CustomSyntaxError(SyntaxError):
    pass
raise CustomSyntaxError("Error message", (None, 1, 5, 'a = sin(3)', 1, 9))
Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    raise CustomSyntaxError("Error message", (None, 1, 5, 'a = sin(3)', 1, 9))
  File "<string>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message

@iritkatriel iritkatriel added the pending The issue will be closed if no feedback is provided label Nov 2, 2023
@stbech
Copy link
Author

stbech commented Nov 2, 2023

For me (Python 3.11.6 on Windows 10) the console does not print the carets in the original error message, only when using the traceback package:

Python 3.11.6 (tags/v3.11.6:8b6ee5b, Oct  2 2023, 14:57:12) [MSC v.1935 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import traceback
>>> class CustomSyntaxError(SyntaxError):
...     pass
...
>>> try:
...     raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
... except Exception as e:
...     traceback.print_exc()
...     print('-'*20)
...     raise e
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<py>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message
--------------------
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "<stdin>", line 2, in <module>
  File "<py>", line 1
    a = sin(3)
        ^
CustomSyntaxError: Error message
>>> raise SyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<py>", line 1
    a = sin(3)
        ^^^^
SyntaxError: Error message

See also this gist for the behavior in a Ipython console or Jupyter Notebook. There neither SyntaxError nor its subclass showed the desired result.
Maybe it has something to do with the error handling in the console, e.g. the console in PyCharm Community Edition works fine for me.

@zedzhen
Copy link

zedzhen commented Apr 8, 2024

Python 3.11.1, 3.12.2 (Windows 10)
IDLE

import sys
import traceback
class CustomSyntaxError(SyntaxError):
    pass

try:
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
except Exception as e:
    traceback.print_exc()
    print('-' * 20, file=sys.stderr)
    raise e from None

Traceback (most recent call last):
  File "<pyshell#4>", line 2, in <module>
  File "<py>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message
--------------------
Traceback (most recent call last):
  File "<pyshell#4>", line 6, in <module>
    raise e from None
  File "<pyshell#4>", line 2, in <module>
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
  File "<py>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message

========= RESTART: D:\path\test.py =========
Traceback (most recent call last):
  File "D:\path\test.py", line 10, in <module>
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
  File "<py>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message
--------------------
Traceback (most recent call last):
  File "D:\path\test.py", line 14, in <module>
    raise e from None
  File "D:\path\test.py", line 10, in <module>
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
  File "<py>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message

cmd

C:\path\Python312>python
Python 3.12.2 (tags/v3.12.2:6abddd9, Feb  6 2024, 21:26:36) [MSC v.1937 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
random, math imported
>>> import sys
>>> import traceback
>>>
>>>
>>> class CustomSyntaxError(SyntaxError):
...     pass
...
>>>
>>> try:
...     raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
... except Exception as e:
...     traceback.print_exc()
...     print('-' * 20, file=sys.stderr)
...     raise e from None
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<py>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message
--------------------
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "<stdin>", line 2, in <module>
  File "<py>", line 1
    a = sin(3)
        ^
CustomSyntaxError: Error message
>>> ^Z


C:\path\Python312>python D:\path\test.py
Traceback (most recent call last):
  File "D:\path\test.py", line 10, in <module>
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
  File "<py>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message
--------------------
Traceback (most recent call last):
  File "D:\path\test.py", line 14, in <module>
    raise e from None
  File "D:\path\test.py", line 10, in <module>
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
  File "<py>", line 1
    a = sin(3)
        ^
CustomSyntaxError: Error message

PyCharm 2023.3.5 (Professional Edition)

Traceback (most recent call last):
  File "D:\path\test.py", line 10, in <module>
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
  File "<py>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message
--------------------
Traceback (most recent call last):
  File "D:\path\test.py", line 14, in <module>
    raise e from None
  File "D:\path\test.py", line 10, in <module>
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
  File "<py>", line 1
    a = sin(3)
        ^
CustomSyntaxError: Error message

test.py

import sys
import traceback


class CustomSyntaxError(SyntaxError):
    pass


try:
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
except Exception as e:
    traceback.print_exc()
    print('-' * 20, file=sys.stderr)
    raise e from None

@zedzhen
Copy link

zedzhen commented Apr 8, 2024

Python 3.13.0a5 (windows 10) correct print

C:\path\Python313>python
Python 3.13.0a5 (tags/v3.13.0a5:076d169, Mar 12 2024, 21:29:03) [MSC v.1938 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
random, math imported
>>> import sys
>>> import traceback
>>>
>>>
>>> class CustomSyntaxError(SyntaxError):
...     pass
...
>>>
>>> try:
...     raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
... except Exception as e:
...     traceback.print_exc()
...     print('-' * 20, file=sys.stderr)
...     raise e from None
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
  File "<py>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message
--------------------
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
    raise e from None
  File "<stdin>", line 2, in <module>
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
  File "<py>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message
>>> ^Z


C:\path\Python313>python D:\path\test.py
Traceback (most recent call last):
  File "D:\path\test.py", line 10, in <module>
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
  File "<py>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message
--------------------
Traceback (most recent call last):
  File "D:\path\test.py", line 14, in <module>
    raise e from None
  File "D:\path\test.py", line 10, in <module>
    raise CustomSyntaxError("Error message", ('<py>', 1, 5, 'a = sin(3)', 1, 9))
  File "<py>", line 1
    a = sin(3)
        ^^^^
CustomSyntaxError: Error message

@nineteendo
Copy link
Contributor

Can confirm on 3.12.4:

Python 3.12.4 (main, Jun  6 2024, 18:26:44) [Clang 15.0.0 (clang-1500.1.0.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from jsonyx import loads
>>> loads("NaN")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/wannes/Library/CloudStorage/OneDrive-Personal/Personal/GitHub/pyvz2/alpha/src/jsonyx/__init__.py", line 248, in loads
    return JSONDecoder(allow=allow).loads(s, filename=filename)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/wannes/Library/CloudStorage/OneDrive-Personal/Personal/GitHub/pyvz2/alpha/src/jsonyx/__init__.py", line 123, in loads
    return self._scanner(filename, s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<string>", line 1
    NaN
    ^
jsonyx._decoder.JSONSyntaxError: NaN is not allowed

It works correctly on 3.13.0b4:

Python 3.13.0b4 (v3.13.0b4:567c38b4eb, Jul 18 2024, 07:28:29) [Clang 15.0.0 (clang-1500.3.9.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from jsonyx import loads
>>> loads("NaN")
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    loads("NaN")
    ~~~~~^^^^^^^
  File "/Users/wannes/Library/CloudStorage/OneDrive-Personal/Personal/GitHub/pyvz2/alpha/src/jsonyx/__init__.py", line 248, in loads
    return JSONDecoder(allow=allow).loads(s, filename=filename)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/wannes/Library/CloudStorage/OneDrive-Personal/Personal/GitHub/pyvz2/alpha/src/jsonyx/__init__.py", line 123, in loads
    return self._scanner(filename, s)
           ~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/Users/wannes/Library/CloudStorage/OneDrive-Personal/Personal/GitHub/pyvz2/alpha/src/jsonyx/_decoder.py", line 398, in scanner
    raise exc.with_traceback(None) from None
  File "<string>", line 1
    NaN
    ^^^
jsonyx._decoder.JSONSyntaxError: NaN is not allowed

@picnixz
Copy link
Member

picnixz commented Dec 2, 2024

The bug is affecting 3.12.6 (haven't tested on 3.12.7) so I'll mark it as 3.12-only.

@picnixz picnixz added the 3.12 bugs and security fixes label Dec 2, 2024
@picnixz picnixz changed the title end_offset is ignored in subclasses of SyntaxError end_offset is ignored in subclasses of SyntaxError (3.12-only) Dec 2, 2024
@picnixz picnixz added stdlib Python modules in the Lib dir topic-repl Related to the interactive shell and removed pending The issue will be closed if no feedback is provided labels Dec 2, 2024
@nineteendo
Copy link
Contributor

Could you do a bisect?

@picnixz
Copy link
Member

picnixz commented Dec 2, 2024

I don't really have time for now (I'm triaging the pending issues), so I'll leave it to anyone willing to do it.

@nineteendo
Copy link
Contributor

nineteendo commented Dec 3, 2024

This also wasn't working on 3.10 and 3.11. It was fixed in 3.13 by #110702.
Should we back port it to fix this? We should fix it differently.

I don't want to choose between end_offset and storing the column number.

@nineteendo
Copy link
Contributor

This fixes the problem:

diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 5f3d249df4..cf84573a8e 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -538,7 +538,6 @@ parse_syntax_error(PyObject *err, PyObject **message, PyObject **filename,
         *offset = hold;
     }
 
-    if (Py_TYPE(err) == (PyTypeObject*)PyExc_SyntaxError) {
     v = PyObject_GetAttr(err, &_Py_ID(end_lineno));
     if (!v) {
         PyErr_Clear();
@@ -570,11 +569,6 @@ parse_syntax_error(PyObject *err, PyObject **message, PyObject **filename,
             goto finally;
         *end_offset = hold;
     }
-    } else {
-        // SyntaxError subclasses
-        *end_lineno = *lineno;
-        *end_offset = -1;
-    }
 
     v = PyObject_GetAttr(err, &_Py_ID(text));
     if (!v)

@nineteendo
Copy link
Contributor

The weird thing is that this check isn't even necessary:

>>> class CustomSyntaxError(SyntaxError):
...     def __init__(self, msg, filename, lineno, offset, text, end_lineno, end_offset):
...         self.msg = msg
...         self.filename = filename
...         self.lineno = lineno
...         self.offset = offset
...         self.text = text
...         # self.end_lineno = end_lineno
...         # self.end_offset = end_offset
... 
>>> raise CustomSyntaxError("Error message", None, 1, 5, 'a = sin(3)', 1, 9)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    a = sin(3)
        ^
CustomSyntaxError: Error message

pablogsal pushed a commit that referenced this issue Dec 11, 2024
#127554)

* `end_offset` is ignored in subclasses of SyntaxError

* 📜🤖 Added by blurb_it.

* Add test

---------

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
pablogsal pushed a commit that referenced this issue Dec 11, 2024
Test `end_offset` in SyntaxError subclass
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Dec 11, 2024
…127830)

Test `end_offset` in SyntaxError subclass
(cherry picked from commit e8f4e27)

Co-authored-by: Nice Zombies <nineteendo19d0@gmail.com>
srinivasreddy pushed a commit to srinivasreddy/cpython that referenced this issue Jan 8, 2025
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Feb 21, 2025
…127830)

Test `end_offset` in SyntaxError subclass
(cherry picked from commit e8f4e27)

Co-authored-by: Nice Zombies <nineteendo19d0@gmail.com>
hugovk pushed a commit that referenced this issue Feb 21, 2025
… (#130407)

Co-authored-by: Nice Zombies <nineteendo19d0@gmail.com>
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
3.12 bugs and security fixes stdlib Python modules in the Lib dir topic-repl Related to the interactive shell type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

7 participants