Skip to content

Inconsistent handling of Unicode (emoji using variation selectors) between curses.window.addstr and curses.window.insstr #135521

Closed as not planned
@zahlman

Description

@zahlman

Bug report

Bug description:

As background: the glyph ❤️ actually consists of two characters: ❤ U+2764 HEAVY BLACK HEART, followed by the unprintable U+FE0F VARIATION SELECTOR-16.

Test script:

import curses


def main(screen):
    screen.clear()
    curses.curs_set(0)
    curses.use_default_colors()
    screen.addstr(0, 0, '\u2764\ufe0ftest')
    screen.addstr('\u2764\ufe0ftest')
    screen.insstr(1, 0, '\u2764\ufe0ftest')
    screen.insstr('\u2764\ufe0ftest')
    try:
        while screen.getch() == -1:
            pass
    except KeyboardInterrupt: # suppress the traceback
        return


if __name__ == '__main__':
    curses.wrapper(main)

The exact appearance of the result is admittedly terminal-dependent, as not all terminals will support rendering the variant-selected red heart. However, the result from .insstr is clearly different in every terminal I could readily test. While .addstr allows the heart emoji to be rendered in terminals that support it (such as gnome-terminal), .insstr only ever displays the ❤ symbol. Further, the spacing is different. It is as though the variation selector had been quietly replaced with a space.

This affects all current versions of Python as far as I can tell, and has probably always affected Python 3 (curses in Python 2 doesn't seem to support Unicode at all).

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-bugAn unexpected behavior, bug, or error

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions