Skip to content

Save a locustfile downloaded from a URL byte for byte - #3577

Merged
cyberw merged 2 commits into
locustio:masterfrom
b84330808:url-locustfile-keep-bytes
Oct 27, 2026
Merged

cyberw merged 2 commits into
locustio:masterfrom
b84330808:url-locustfile-keep-bytes

Conversation

@b84330808

Copy link
Copy Markdown
Contributor

locust -f <url> saves the download with open(path, "w").write(response.text). Non-ASCII text in the locustfile (a Japanese comment, print("café")) breaks in two ways:

  • If the server sends no charset (python -m http.server sends text/x-python; many S3/nginx setups send bare text/plain), requests decodes the body as ISO-8859-1 and the file is saved double-encoded, so print("こんにちは") prints ããã«ã¡ã¯.
  • On Windows the file is written in the ANSI code page. Even with charset=utf-8 (raw.githubusercontent.com), a Japanese comment is saved as cp932 and the import fails with SyntaxError: (unicode error) 'utf-8' codec can't decode byte 0x82 in position 0: invalid start byte. A character the code page can't encode fails while saving (UnicodeEncodeError: 'cp932' codec can't encode character ...).

The download is Python source, so this saves response.content unchanged and lets Python decode it on import (UTF-8, or the file's coding line). ast.parse() now checks the same bytes.

Tests:

  • test_locustfile_from_url_is_saved_byte_for_byte serves a non-ASCII locustfile from a local gevent server as text/x-python and compares the saved bytes. It fails on master (double-encoded bytes in UTF-8 mode, UnicodeEncodeError with cp932) and passes with the change.
  • test_locustfile_from_url compared the GitHub download with examples/basic.py using filecmp. On Windows that file is checked out with CRLF (*.py text), and it only matched because the old text-mode write also turned LF into CRLF. It now compares the two as text.

I used Claude Code to write this change.

b84330808 and others added 2 commits October 26, 2026 17:11
download_locustfile_from_url() wrote response.text to a text-mode file
opened with the locale encoding. When the server sends no charset,
requests decodes text/* bodies as ISO-8859-1, so non-ASCII characters
were double-encoded. On Windows the locale encoding (cp1252, cp932)
either cannot encode the text (UnicodeEncodeError) or writes bytes that
Python then refuses to import as UTF-8 source.

Write response.content in binary mode instead, and check it with
ast.parse() on the same bytes, so Python decodes the file the same way
when it imports it. test_locustfile_from_url now compares the files as
text, because a Windows checkout of examples/basic.py has CRLF line
endings.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@cyberw
cyberw merged commit 8c86553 into locustio:master Oct 27, 2026
21 checks passed
@cyberw

cyberw commented Oct 27, 2026

Copy link
Copy Markdown
Collaborator

nice

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.

2 participants