diff --git a/changelog.rst b/changelog.rst index 8864a88d2..046b9a8e2 100644 --- a/changelog.rst +++ b/changelog.rst @@ -4,6 +4,8 @@ Upcoming (TBD) Bug fixes: ---------- * Restore cursor shape behaviour for Emacs mode +* Fix ``TypeError: cannot use a string pattern on a bytes-like object`` when + completion metadata comes back as bytes (e.g. ``SQL_ASCII`` client encoding). Features: --------- diff --git a/pgcli/pgcompleter.py b/pgcli/pgcompleter.py index 7430be3c4..284c6da48 100644 --- a/pgcli/pgcompleter.py +++ b/pgcli/pgcompleter.py @@ -141,6 +141,11 @@ def __init__(self, smart_completion=True, pgspecial=None, settings=None): self.all_completions = set(self.keywords + self.functions) def escape_name(self, name): + if isinstance(name, bytes): + # Identifiers come back as bytes when the client encoding is one + # psycopg cannot decode (e.g. SQL_ASCII), see issue #1405. + name = name.decode("utf-8", "replace") + if name and ((not self.name_pattern.match(name)) or (name.upper() in self.reserved_words) or (name.upper() in self.functions)): name = '"%s"' % name diff --git a/tests/test_pgcompleter.py b/tests/test_pgcompleter.py index a9f390d76..028d02524 100644 --- a/tests/test_pgcompleter.py +++ b/tests/test_pgcompleter.py @@ -92,3 +92,19 @@ def test_generate_alias_prefers_alias_over_upper_case_name(table_name, alias_map ) def test_generate_alias_prefers_upper_case_name_over_underscore_name(table_name, alias): assert pgcompleter.generate_alias(table_name) == alias + + +@pytest.mark.parametrize( + "name, expected", + [ + (b"pg_catalog", "pg_catalog"), + (b"public", "public"), + (b"Mixed Case", '"Mixed Case"'), + (b"select", '"select"'), + ], +) +def test_escape_name_accepts_bytes(name, expected): + """Identifiers arrive as bytes under encodings psycopg cannot decode.""" + completer = pgcompleter.PGCompleter() + assert completer.escape_name(name) == expected + assert completer.escaped_names([name]) == [expected]