Skip to content

fix: escape backslashes in set_key to preserve round-trip#666

Open
gaoflow wants to merge 1 commit into
theskumar:mainfrom
gaoflow:fix-set-key-backslash-roundtrip
Open

fix: escape backslashes in set_key to preserve round-trip#666
gaoflow wants to merge 1 commit into
theskumar:mainfrom
gaoflow:fix-set-key-backslash-roundtrip

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 24, 2026

Copy link
Copy Markdown

Bug

set_key() writes values wrapped in single quotes, and the parser decodes \\ as a literal backslash via decode_escapes(). But set_key() only escaped single-quote characters (\'), not backslashes themselves. This meant any value containing two or more consecutive backslashes lost one during round-trip:

Also reproduces for Windows paths (C:\Users\...) and any value with \\ sequences.

Root Cause

The parser's _single_quote_escapes regex matches both \' and \\, decoding them via codecs.decode(..., 'unicode-escape'). When set_key writes a value containing literal \\, the parser interprets it as an escaped backslash and decodes it to \, losing one backslash on each consecutive pair.

Fix

Escape backslashes in addition to single-quotes in set_key(), before wrapping in single quotes. The order is important: backslashes must be escaped first (\\ -> \\\\), then single-quotes (' -> \').

Diff

  • src/dotenv/main.py: +2/-0 (escape backslashes before single-quotes)
  • tests/test_main.py: +23 (parametrized round-trip regression test covering 0-3 backslashes, Windows paths, and mixed quotes+backslashes)

set_key() writes values wrapped in single quotes, and the parser
decodes \\ as a literal backslash via decode_escapes().  But
set_key() only escaped single-quote characters (\'), not backslashes
themselves.  This meant any value containing two or more consecutive
backslashes lost one during round-trip:

    set_key(path, 'K', 'a\\\\b')
    dotenv_values(path)['K']  # -> 'a\\b' (lost one backslash)

The parser's _single_quote_escapes regex matches both \\' and \\\\,
so backslashes MUST be doubled when writing to preserve them.  Fix by
escaping backslashes before single-quotes in the value quoting step.

- src/dotenv/main.py: +2/-0
- tests/test_main.py: +23 (parametrized round-trip regression test)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant