Literal characters outside of expressions were copied verbatim during
expansion, so a non-ASCII literal such as the accented e in "cafe/{var}"
was emitted raw instead of percent-encoded. RFC 6570 Section 3.1 requires
literal text that is not URI-legal to be encoded as its UTF-8
percent-encoded triplets.
_expand now encodes each literal run around the expanded expressions
instead of relying on a single re.sub pass, which cannot do this without
re-encoding the already-encoded expansion output. Existing percent-encoded
triplets in the literal are preserved. This matches the official
uritemplate-test "Literal Encoding" cases, added here to the bundled
fixtures.
RFC 6570 Section 3.1 requires literal text (the characters outside of {...} expressions) that is not allowed in a URI to be copied to the result as its UTF-8 percent-encoded octets. uritemplate copies literals verbatim, so non-ASCII literal text is emitted unencoded:
_expand relied on a single template_re.sub() pass, which copies everything outside an expression as-is. It now encodes each literal run around the expanded expressions in one left-to-right pass. A single sub cannot do this, because re-quoting the whole result afterwards would double-encode the expansion output. Existing %XX triplets inside a literal are preserved, so already-encoded literals (x%20y/{var}) and partial-expansion round-trips stay stable.
This is pinned by the official uritemplate-test "Additional Examples 8: Literal Encoding" group, which was absent from the bundled fixtures; it is added here, along with unit tests for the multibyte, reserved-character, and pre-encoded boundaries. The full upstream suite (spec examples, by-section, and extended tests) passes.