• Kirill Smelkov's avatar
    golang_str: Fix bstr/ustr .__str__ to always return bstr/ustr even for subclasses · d4dcf5dd
    Kirill Smelkov authored
    This behaviour is provided by builtin str and we were not following it:
    
        $ python3
        Python 3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0] on linux
        Type "help", "copyright", "credits" or "license" for more information.
        >>> class SSS(str): pass
        ...
        >>> z = SSS('abc')
        >>> z
        'abc'
        >>> type(z)
        <class '__main__.SSS'>
        >>> q = str(z)
        >>> q
        'abc'
        >>> type(q)
        <class 'str'>
        >>> r = z.__str__()
        >>> r
        'abc'
        >>> type(r)
        <class 'str'>                       <-- NOTE str, not __main__.SSS
    
        $ gpython               # with str patched to be ustr
        >>> class SSS(str): pass
        >>> z = SSS('abc')
        >>> z
        'abc'
        >>> type(z)
        <class '__main__.SSS'>
        >>> q = str(z)
        >>> q
        'abc'
        >>> type(q)
        <class 'str'>
        >>> r = z.__str__()
        >>> r
        'abc'
        >>> type(r)
        <class '__main__.SSS'>              <-- NOTE not str
    
    which leads to crash during IPython startup on py3.11:
    
        $ gpython -m IPython    # with str patched to be ustr
        Traceback (most recent call last):
          File "/home/kirr/src/tools/go/py3.venv/bin/gpython", line 8, in <module>
            sys.exit(main())
                     ^^^^^^
          File "/home/kirr/src/tools/go/pygolang-master/gpython/__init__.py", line 478, in main
            pymain(argv, init)
          File "/home/kirr/src/tools/go/pygolang-master/gpython/__init__.py", line 291, in pymain
            run(mmain)
          File "/home/kirr/src/tools/go/pygolang-master/gpython/__init__.py", line 162, in run
            runpy._run_module_as_main(mod)
          File "<frozen runpy>", line 198, in _run_module_as_main
          File "<frozen runpy>", line 88, in _run_code
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/IPython/__main__.py", line 15, in <module>
            start_ipython()
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/IPython/__init__.py", line 128, in start_ipython
            return launch_new_instance(argv=argv, **kwargs)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/traitlets/config/application.py", line 1042, in launch_instance
            app.initialize(argv)
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/traitlets/config/application.py", line 113, in inner
            return method(app, *args, **kwargs)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/IPython/terminal/ipapp.py", line 279, in initialize
            self.init_shell()
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/IPython/terminal/ipapp.py", line 293, in init_shell
            self.shell = self.interactive_shell_class.instance(parent=self,
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/traitlets/config/configurable.py", line 551, in instance
            inst = cls(*args, **kwargs)
                   ^^^^^^^^^^^^^^^^^^^^
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/IPython/terminal/interactiveshell.py", line 856, in __init__
            self.init_prompt_toolkit_cli()
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/IPython/terminal/interactiveshell.py", line 648, in init_prompt_toolkit_cli
            **self._extra_prompt_options(),
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/IPython/terminal/interactiveshell.py", line 751, in _extra_prompt_options
            "lexer": IPythonPTLexer(),
                     ^^^^^^^^^^^^^^^^
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/IPython/terminal/ptutils.py", line 177, in __init__
            self.python_lexer = PygmentsLexer(l.Python3Lexer)
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/prompt_toolkit/lexers/pygments.py", line 198, in __init__
            self.pygments_lexer = pygments_lexer_cls(
                                  ^^^^^^^^^^^^^^^^^^^
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/pygments/lexer.py", line 647, in __call__
            cls._tokens = cls.process_tokendef('', cls.get_tokendefs())
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/pygments/lexer.py", line 586, in process_tokendef
            cls._process_state(tokendefs, processed, state)
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/pygments/lexer.py", line 549, in _process_state
            tokens.extend(cls._process_state(unprocessed, processed,
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
          File "/home/kirr/src/tools/go/py3.venv/lib/python3.11/site-packages/pygments/lexer.py", line 533, in _process_state
            assert type(state) is str, "wrong state name %r (%r)" % (state, type(state))
                   ^^^^^^^^^^^^^^^^^^
        AssertionError: wrong state name 'keywords' (<class 'pygments.lexer.include'>)
    
        If you suspect this is an IPython 8.12.0 bug, please report it at:
            https://github.com/ipython/ipython/issues
        or send an email to the mailing list at ipython-dev@python.org
    
        You can print a more detailed traceback right now with "%tb", or use "%debug"
        to interactively debug it.
    
        Extra-detailed tracebacks for bug-reporting purposes can be enabled via:
            c.Application.verbose_crash=True
    
    Here pygments define
    
        class include(str):
            pass
    
    and wants `str(obj)` to return str, not include if obj was instance of include.
    
    -> Adjust bstr/ustr .__str__() to always return bstr/ustr even for
    subclassed.
    
    For consistency, do the same for .__unicode__ . In case a
    subclass wants its __str__, or __unicode__ to return self
    without casting to bstr/ustr, it can override those methods.
    d4dcf5dd
_golang_str.pyx 81.7 KB