Instructions to use unsloth/Qwen3.8-27B-GGUF with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use unsloth/Qwen3.8-27B-GGUF with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL # Run inference directly in the terminal: llama cli -hf unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL # Run inference directly in the terminal: llama cli -hf unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL # Run inference directly in the terminal: ./llama-cli -hf unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL # Run inference directly in the terminal: ./build/bin/llama-cli -hf unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL
Use Docker
docker model run hf.co/unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL
- LM Studio
- Jan
- Ollama
How to use unsloth/Qwen3.8-27B-GGUF with Ollama:
ollama run hf.co/unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL
- Unsloth Studio
How to use unsloth/Qwen3.8-27B-GGUF with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for unsloth/Qwen3.8-27B-GGUF to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for unsloth/Qwen3.8-27B-GGUF to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for unsloth/Qwen3.8-27B-GGUF to start chatting
- Pi
How to use unsloth/Qwen3.8-27B-GGUF with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL
Configure the model in Pi
# Install Pi: npm install -g @mariozechner/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL" } ] } } }Run Pi
# Start Pi in your project directory: pi
- OpenClaw new
How to use unsloth/Qwen3.8-27B-GGUF with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
- Docker Model Runner
How to use unsloth/Qwen3.8-27B-GGUF with Docker Model Runner:
docker model run hf.co/unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL
- Lemonade
How to use unsloth/Qwen3.8-27B-GGUF with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL
Run and chat with the model
lemonade run user.Qwen3.8-27B-GGUF-UD-Q4_K_XL
List all available models
lemonade list
- Hermes Agent
How to use unsloth/Qwen3.8-27B-GGUF with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default unsloth/Qwen3.8-27B-GGUF:UD-Q4_K_XL
Run Hermes
hermes
- Atomic Chat
codeneedle benchmark results
ziskind code needle results:
K:\codeneedle\codeneedle>venv\Scripts\activate.bat
(venv) K:\codeneedle\codeneedle>python bench.py run --corpus http_server --model Qwen3.8-27B-noMTP-Q8 --base-url http://localhost:8080
(no model config 'Qwen3.8-27B-noMTP-Q8' found; using as raw model identifier with defaults)
Source: http_server.py (49,924 chars, 1,354 lines, 1 file(s))
Extracted 11 named functions with β₯20 body lines
Selected 11 target function(s):
- _url_collapse_path line 924 body_lines=44 (http_server.py)
- parse_request line 273 body_lines=115 (http_server.py)
- handle_one_request line 408 body_lines=35 (http_server.py)
- send_error line 453 body_lines=51 (http_server.py)
- log_message line 588 body_lines=24 (http_server.py)
- send_head line 702 body_lines=86 (http_server.py)
- list_directory line 790 body_lines=58 (http_server.py)
- translate_path line 850 body_lines=28 (http_server.py)
- guess_type line 896 body_lines=23 (http_server.py)
- is_cgi line 1039 body_lines=23 (http_server.py)
- run_cgi line 1076 body_lines=195 (http_server.py)
Pre-flight: probing context fit with a 50,553-char prompt (max_tokens=1)...
Pre-flight OK.
[1/11] _url_collapse_path β prompt 50,553 chars, waiting on model...
response: 771 chars in 21.4s
=== _url_collapse_path [β[32mPASSβ[0m] matched=20/20 hallucinated=0 bonus=0 ===
-- model output --
β[37m """β[0m
β[37m Given a URL path, remove extra '/'s and '.' path elements and collapseβ[0m
β[37m any '..' references and returns a collapsed path.β[0m
β[37mβ[0m
β[37m Implements something akin to RFC-2396 5.2 step 6 to parse relative paths.β[0m
β[37m The utility of this function is limited to is_cgi method and helpsβ[0m
β[37m preventing some security attacks.β[0m
β[37mβ[0m
β[37m Returns: The reconstituted URL, which will always start with a '/'.β[0m
β[37mβ[0m
β[37m Raises: IndexError if too many '..' occur within the path.β[0m
β[37mβ[0m
β[37m """β[0m
β[37m # Query component should not be involved.β[0m
β[37m path, _, query = path.partition('?')β[0m
β[37m path = urllib.parse.unquote(path)β[0m
β[37mβ[0m
β[37m # Similar to os.path.split(os.path.normpath(path)) but specific to URLβ[0m
β[37m # path semantics rather than local operating system semantics.β[0m
β[37m path_parts = path.split('/')β[0m
[2/11] parse_request β prompt 50,538 chars, waiting on model...
response: 786 chars in 41.9s
=== parse_request [β[32mPASSβ[0m] matched=20/20 hallucinated=0 bonus=0 ===
-- model output --
β[37m """Parse a request (internal).β[0m
β[37mβ[0m
β[37m The request should be stored in self.raw_requestline; the resultsβ[0m
β[37m are in self.command, self.path, self.request_version andβ[0m
β[37m self.headers.β[0m
β[37mβ[0m
β[37m Return True for success, False for failure; on failure, any relevantβ[0m
β[37m error response has already been sent back.β[0m
β[37mβ[0m
β[37m """β[0m
β[37m is_http_0_9 = Falseβ[0m
β[37m self.command = None # set in case of error on the first lineβ[0m
β[37m self.request_version = version = self.default_request_versionβ[0m
β[37m self.close_connection = Trueβ[0m
β[37m requestline = str(self.raw_requestline, 'iso-8859-1')β[0m
β[37m requestline = requestline.rstrip('\r\n')β[0m
β[37m self.requestline = requestlineβ[0m
β[37m words = requestline.split()β[0m
β[37m if len(words) == 0:β[0m
β[37m return Falseβ[0m
[3/11] handle_one_request β prompt 50,553 chars, waiting on model...
response: 768 chars in 31.4s
=== handle_one_request [β[32mPASSβ[0m] matched=20/20 hallucinated=0 bonus=0 ===
-- model output --
β[37m """Handle a single HTTP request.β[0m
β[37mβ[0m
β[37m You normally don't need to override this method; see the classβ[0m
β[37m doc string for information on how to handle specific HTTPβ[0m
β[37m commands such as GET and POST.β[0m
β[37mβ[0m
β[37m """β[0m
β[37m try:β[0m
β[37m self.raw_requestline = self.rfile.readline(65537)β[0m
β[37m if len(self.raw_requestline) > 65536:β[0m
β[37m self.requestline = ''β[0m
β[37m self.request_version = ''β[0m
β[37m self.command = ''β[0m
β[37m self.send_error(HTTPStatus.REQUEST_URI_TOO_LONG)β[0m
β[37m returnβ[0m
β[37m if not self.raw_requestline:β[0m
β[37m self.close_connection = Trueβ[0m
β[37m returnβ[0m
β[37m if not self.parse_request():β[0m
β[37m # An error code has been sent, just exitβ[0m
[4/11] send_error β prompt 50,529 chars, waiting on model...
response: 725 chars in 55.8s
=== send_error [β[32mPASSβ[0m] matched=20/20 hallucinated=0 bonus=0 ===
-- model output --
β[37m """Send and log an error reply.β[0m
β[37mβ[0m
β[37m Arguments areβ[0m
β[37m * code: an HTTP error codeβ[0m
β[37m 3 digitsβ[0m
β[37m * message: a simple optional 1 line reason phrase.β[0m
β[37m *( HTAB / SP / VCHAR / %x80-FF )β[0m
β[37m defaults to short entry matching the response codeβ[0m
β[37m * explain: a detailed message defaults to the long entryβ[0m
β[37m matching the response code.β[0m
β[37mβ[0m
β[37m This sends an error response (so it must be called before anyβ[0m
β[37m output has been generated), logs the error, and finally sendsβ[0m
β[37m a piece of HTML explaining the error to the user.β[0m
β[37mβ[0m
β[37m """β[0m
β[37mβ[0m
β[37m try:β[0m
β[37m shortmsg, longmsg = self.responses[code]β[0m
β[37m except KeyError:β[0m
[5/11] log_message β prompt 50,532 chars, waiting on model...
response: 649 chars in 18.5s
=== log_message [β[32mPASSβ[0m] matched=20/20 hallucinated=0 bonus=0 ===
-- model output --
β[37m """Log an arbitrary message.β[0m
β[37mβ[0m
β[37m This is used by all other logging functions. Overrideβ[0m
β[37m it if you have specific logging wishes.β[0m
β[37mβ[0m
β[37m The first argument, FORMAT, is a format string for theβ[0m
β[37m message to be logged. If the format string containsβ[0m
β[37m any % escapes requiring parameters, they should beβ[0m
β[37m specified as subsequent arguments (it's just likeβ[0m
β[37m printf!).β[0m
β[37mβ[0m
β[37m The client ip and current date/time are prefixed toβ[0m
β[37m every message.β[0m
β[37mβ[0m
β[37m Unicode control characters are replaced with escaped hexβ[0m
β[37m before writing the output to stderr.β[0m
β[37mβ[0m
β[37m """β[0m
β[37mβ[0m
β[37m message = format % argsβ[0m
[6/11] send_head β prompt 50,526 chars, waiting on model...
response: 905 chars in 77.5s
=== send_head [β[32mPASSβ[0m] matched=19/20 hallucinated=0 bonus=1 ===
-- model output --
β[37m """Common code for GET and HEAD commands.β[0m
β[37mβ[0m
β[37m This sends the response code and MIME headers.β[0m
β[37mβ[0m
β[37m Return value is either a file object (which has to be copiedβ[0m
β[37m to the outputfile by the caller unless the command was HEAD,β[0m
β[37m and must be closed by the caller under all circumstances), orβ[0m
β[37m None, in which case the caller has nothing further to do.β[0m
β[37mβ[0m
β[37m """β[0m
β[37m path = self.translate_path(self.path)β[0m
β[37m f = Noneβ[0m
β[37m if os.path.isdir(path):β[0m
β[37m parts = urllib.parse.urlsplit(self.path)β[0m
β[37m if not parts.path.endswith(('/', '%2f', '%2F')):β[0m
β[37m # redirect browser - doing basically what apache doesβ[0m
β[37m self.send_response(HTTPStatus.MOVED_PERMANENTLY)β[0m
β[37m new_parts = (parts[0], parts[1], parts[2] + '/',β[0m
β[37m parts[3], parts[4])β[0m
β[36m self.send_header("Location", new_url)β[0m
-- missing expected lines --
β[38;5;208m new_url = urllib.parse.urlunsplit(new_parts)β[0m
[7/11] list_directory β prompt 50,541 chars, waiting on model...
response: 685 chars in 29.1s
=== list_directory [β[32mPASSβ[0m] matched=20/20 hallucinated=0 bonus=0 ===
-- model output --
β[37m """Helper to produce a directory listing (absent index.html).β[0m
β[37mβ[0m
β[37m Return value is either a file object, or None (indicating anβ[0m
β[37m error). In either case, the headers are sent, making theβ[0m
β[37m interface the same as for send_head().β[0m
β[37mβ[0m
β[37m """β[0m
β[37m try:β[0m
β[37m list = os.listdir(path)β[0m
β[37m except OSError:β[0m
β[37m self.send_error(β[0m
β[37m HTTPStatus.NOT_FOUND,β[0m
β[37m "No permission to list directory")β[0m
β[37m return Noneβ[0m
β[37m list.sort(key=lambda a: a.lower())β[0m
β[37m r = []β[0m
β[37m displaypath = self.pathβ[0m
β[37m displaypath = displaypath.split('#', 1)[0]β[0m
β[37m displaypath = displaypath.split('?', 1)[0]β[0m
β[37m try:β[0m
[8/11] translate_path β prompt 50,541 chars, waiting on model...
response: 778 chars in 27.0s
=== translate_path [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""Translate a /-separated PATH to the local filename syntax.β[0m
β[37mβ[0m
β[37m Components that mean special things to the local file systemβ[0m
β[37m (e.g. drive or directory names) are ignored. (XXX They shouldβ[0m
β[37m probably be diagnosed.)β[0m
β[37mβ[0m
β[37m """β[0m
β[37m # abandon query parametersβ[0m
β[37m path = path.split('#', 1)[0]β[0m
β[37m path = path.split('?', 1)[0]β[0m
β[37m # Don't forget explicit trailing slash when normalizing. Issue17324β[0m
β[37m try:β[0m
β[37m path = urllib.parse.unquote(path, errors='surrogatepass')β[0m
β[37m except UnicodeDecodeError:β[0m
β[37m path = urllib.parse.unquote(path)β[0m
β[37m trailing_slash = path.endswith('/')β[0m
β[37m path = posixpath.normpath(path)β[0m
β[37m words = path.split('/')β[0m
β[37m words = filter(None, words)β[0m
β[37m path = self.directoryβ[0m
-- missing expected lines --
β[38;5;208m """Translate a /-separated PATH to the local filename syntax.β[0m
[9/11] guess_type β prompt 50,529 chars, waiting on model...
response: 745 chars in 28.5s
=== guess_type [β[32mPASSβ[0m] matched=20/20 hallucinated=0 bonus=0 ===
-- model output --
β[37m """Guess the type of a file.β[0m
β[37mβ[0m
β[37m Argument is a PATH (a filename).β[0m
β[37mβ[0m
β[37m Return value is a string of the form type/subtype,β[0m
β[37m usable for a MIME Content-type header.β[0m
β[37mβ[0m
β[37m The default implementation looks the file's extensionβ[0m
β[37m up in the table self.extensions_map, using application/octet-streamβ[0m
β[37m as a default; however it would be permissible (ifβ[0m
β[37m slow) to look inside the data to make a better guess.β[0m
β[37mβ[0m
β[37m """β[0m
β[37m base, ext = posixpath.splitext(path)β[0m
β[37m if ext in self.extensions_map:β[0m
β[37m return self.extensions_map[ext]β[0m
β[37m ext = ext.lower()β[0m
β[37m if ext in self.extensions_map:β[0m
β[37m return self.extensions_map[ext]β[0m
β[37m guess, _ = mimetypes.guess_file_type(path)β[0m
[10/11] is_cgi β prompt 50,517 chars, waiting on model...
response: 922 chars in 44.5s
=== is_cgi [β[32mPASSβ[0m] matched=20/20 hallucinated=0 bonus=0 ===
-- model output --
β[37m """Test whether self.path corresponds to a CGI script.β[0m
β[37mβ[0m
β[37m Returns True and updates the cgi_info attribute to the tupleβ[0m
β[37m (dir, rest) if self.path requires running a CGI script.β[0m
β[37m Returns False otherwise.β[0m
β[37mβ[0m
β[37m If any exception is raised, the caller should assume thatβ[0m
β[37m self.path was rejected as invalid and act accordingly.β[0m
β[37mβ[0m
β[37m The default implementation tests whether the normalized urlβ[0m
β[37m path begins with one of the strings in self.cgi_directoriesβ[0m
β[37m (and the next character is a '/' or the end of the string).β[0m
β[37mβ[0m
β[37m """β[0m
β[37m collapsed_path = _url_collapse_path(self.path)β[0m
β[37m dir_sep = collapsed_path.find('/', 1)β[0m
β[37m while dir_sep > 0 and not collapsed_path[:dir_sep] in self.cgi_directories:β[0m
β[37m dir_sep = collapsed_path.find('/', dir_sep+1)β[0m
β[37m if dir_sep > 0:β[0m
β[37m head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:]β[0m
[11/11] run_cgi β prompt 50,520 chars, waiting on model...
response: 685 chars in 31.8s
=== run_cgi [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""Execute a CGI script."""β[0m
β[37m dir, rest = self.cgi_infoβ[0m
β[37m path = dir + '/' + restβ[0m
β[37m i = path.find('/', len(dir)+1)β[0m
β[37m while i >= 0:β[0m
β[37m nextdir = path[:i]β[0m
β[37m nextrest = path[i+1:]β[0m
β[37mβ[0m
β[37m scriptdir = self.translate_path(nextdir)β[0m
β[37m if os.path.isdir(scriptdir):β[0m
β[37m dir, rest = nextdir, nextrestβ[0m
β[37m i = path.find('/', len(dir)+1)β[0m
β[37m else:β[0m
β[37m breakβ[0m
β[37mβ[0m
β[37m # find an explicit query string, if present.β[0m
β[37m rest, _, query = rest.partition('?')β[0m
β[37mβ[0m
β[37m # dissect the part after the directory name into a script name &β[0m
β[37m # a possible additional path, to be stored in PATH_INFO.β[0m
-- missing expected lines --
β[38;5;208m """Execute a CGI script."""β[0m
β[1m=== SUMMARY ===β[0m
Pass: 11/11
Primary lines matched: 217/220
Hallucinated lines: 2
Bonus (extra correct): 1
per-function:
β[32mββ[0m _url_collapse_path matched=20/20 halluc= 0 bonus= 0
β[32mββ[0m parse_request matched=20/20 halluc= 0 bonus= 0
β[32mββ[0m handle_one_request matched=20/20 halluc= 0 bonus= 0
β[32mββ[0m send_error matched=20/20 halluc= 0 bonus= 0
β[32mββ[0m log_message matched=20/20 halluc= 0 bonus= 0
β[32mββ[0m send_head matched=19/20 halluc= 0 bonus= 1
β[32mββ[0m list_directory matched=20/20 halluc= 0 bonus= 0
β[32mββ[0m translate_path matched=19/20 halluc= 1 bonus= 0
β[32mββ[0m guess_type matched=20/20 halluc= 0 bonus= 0
β[32mββ[0m is_cgi matched=20/20 halluc= 0 bonus= 0
β[32mββ[0m run_cgi matched=19/20 halluc= 1 bonus= 0
Results dumped to K:\codeneedle\codeneedle\results\http_server__Qwen3.8-27B-noMTP-Q8.json
(venv) K:\codeneedle\codeneedle>python bench.py run --corpus http_server --model Qwen3.8-27B-noMTP-Q8_XL --base-url http://localhost:8080
(no model config 'Qwen3.8-27B-noMTP-Q8_XL' found; using as raw model identifier with defaults)
Source: http_server.py (49,924 chars, 1,354 lines, 1 file(s))
Extracted 11 named functions with β₯20 body lines
Selected 11 target function(s):
- _url_collapse_path line 924 body_lines=44 (http_server.py)
- parse_request line 273 body_lines=115 (http_server.py)
- handle_one_request line 408 body_lines=35 (http_server.py)
- send_error line 453 body_lines=51 (http_server.py)
- log_message line 588 body_lines=24 (http_server.py)
- send_head line 702 body_lines=86 (http_server.py)
- list_directory line 790 body_lines=58 (http_server.py)
- translate_path line 850 body_lines=28 (http_server.py)
- guess_type line 896 body_lines=23 (http_server.py)
- is_cgi line 1039 body_lines=23 (http_server.py)
- run_cgi line 1076 body_lines=195 (http_server.py)
Pre-flight: probing context fit with a 50,553-char prompt (max_tokens=1)...
Pre-flight OK.
[1/11] _url_collapse_path β prompt 50,553 chars, waiting on model...
response: 767 chars in 57.5s
=== _url_collapse_path [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""β[0m
β[37m Given a URL path, remove extra '/'s and '.' path elements and collapseβ[0m
β[37m any '..' references and returns a collapsed path.β[0m
β[37mβ[0m
β[37m Implements something akin to RFC-2396 5.2 step 6 to parse relative paths.β[0m
β[37m The utility of this function is limited to is_cgi method and helpsβ[0m
β[37m preventing some security attacks.β[0m
β[37mβ[0m
β[37m Returns: The reconstituted URL, which will always start with a '/'.β[0m
β[37mβ[0m
β[37m Raises: IndexError if too many '..' occur within the path.β[0m
β[37mβ[0m
β[37m """β[0m
β[37m # Query component should not be involved.β[0m
β[37m path, _, query = path.partition('?')β[0m
β[37m path = urllib.parse.unquote(path)β[0m
β[37mβ[0m
β[37m # Similar to os.path.split(os.path.normpath(path)) but specific to URLβ[0m
β[37m # path semantics rather than local operating system semantics.β[0m
β[37m path_parts = path.split('/')β[0m
-- missing expected lines --
β[38;5;208m """β[0m
[2/11] parse_request β prompt 50,538 chars, waiting on model...
response: 778 chars in 59.3s
=== parse_request [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""Parse a request (internal).β[0m
β[37mβ[0m
β[37m The request should be stored in self.raw_requestline; the resultsβ[0m
β[37m are in self.command, self.path, self.request_version andβ[0m
β[37m self.headers.β[0m
β[37mβ[0m
β[37m Return True for success, False for failure; on failure, any relevantβ[0m
β[37m error response has already been sent back.β[0m
β[37mβ[0m
β[37m """β[0m
β[37m is_http_0_9 = Falseβ[0m
β[37m self.command = None # set in case of error on the first lineβ[0m
β[37m self.request_version = version = self.default_request_versionβ[0m
β[37m self.close_connection = Trueβ[0m
β[37m requestline = str(self.raw_requestline, 'iso-8859-1')β[0m
β[37m requestline = requestline.rstrip('\r\n')β[0m
β[37m self.requestline = requestlineβ[0m
β[37m words = requestline.split()β[0m
β[37m if len(words) == 0:β[0m
β[37m return Falseβ[0m
-- missing expected lines --
β[38;5;208m """Parse a request (internal).β[0m
[3/11] handle_one_request β prompt 50,553 chars, waiting on model...
response: 760 chars in 38.8s
=== handle_one_request [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""Handle a single HTTP request.β[0m
β[37mβ[0m
β[37m You normally don't need to override this method; see the classβ[0m
β[37m doc string for information on how to handle specific HTTPβ[0m
β[37m commands such as GET and POST.β[0m
β[37mβ[0m
β[37m """β[0m
β[37m try:β[0m
β[37m self.raw_requestline = self.rfile.readline(65537)β[0m
β[37m if len(self.raw_requestline) > 65536:β[0m
β[37m self.requestline = ''β[0m
β[37m self.request_version = ''β[0m
β[37m self.command = ''β[0m
β[37m self.send_error(HTTPStatus.REQUEST_URI_TOO_LONG)β[0m
β[37m returnβ[0m
β[37m if not self.raw_requestline:β[0m
β[37m self.close_connection = Trueβ[0m
β[37m returnβ[0m
β[37m if not self.parse_request():β[0m
β[37m # An error code has been sent, just exitβ[0m
-- missing expected lines --
β[38;5;208m """Handle a single HTTP request.β[0m
[4/11] send_error β prompt 50,529 chars, waiting on model...
response: 717 chars in 97.9s
=== send_error [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""Send and log an error reply.β[0m
β[37mβ[0m
β[37m Arguments areβ[0m
β[37m * code: an HTTP error codeβ[0m
β[37m 3 digitsβ[0m
β[37m * message: a simple optional 1 line reason phrase.β[0m
β[37m *( HTAB / SP / VCHAR / %x80-FF )β[0m
β[37m defaults to short entry matching the response codeβ[0m
β[37m * explain: a detailed message defaults to the long entryβ[0m
β[37m matching the response code.β[0m
β[37mβ[0m
β[37m This sends an error response (so it must be called before anyβ[0m
β[37m output has been generated), logs the error, and finally sendsβ[0m
β[37m a piece of HTML explaining the error to the user.β[0m
β[37mβ[0m
β[37m """β[0m
β[37mβ[0m
β[37m try:β[0m
β[37m shortmsg, longmsg = self.responses[code]β[0m
β[37m except KeyError:β[0m
-- missing expected lines --
β[38;5;208m """Send and log an error reply.β[0m
[5/11] log_message β prompt 50,532 chars, waiting on model...
response: 641 chars in 39.9s
=== log_message [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""Log an arbitrary message.β[0m
β[37mβ[0m
β[37m This is used by all other logging functions. Overrideβ[0m
β[37m it if you have specific logging wishes.β[0m
β[37mβ[0m
β[37m The first argument, FORMAT, is a format string for theβ[0m
β[37m message to be logged. If the format string containsβ[0m
β[37m any % escapes requiring parameters, they should beβ[0m
β[37m specified as subsequent arguments (it's just likeβ[0m
β[37m printf!).β[0m
β[37mβ[0m
β[37m The client ip and current date/time are prefixed toβ[0m
β[37m every message.β[0m
β[37mβ[0m
β[37m Unicode control characters are replaced with escaped hexβ[0m
β[37m before writing the output to stderr.β[0m
β[37mβ[0m
β[37m """β[0m
β[37mβ[0m
β[37m message = format % argsβ[0m
-- missing expected lines --
β[38;5;208m """Log an arbitrary message.β[0m
[6/11] send_head β prompt 50,526 chars, waiting on model...
response: 904 chars in 109.2s
=== send_head [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""Common code for GET and HEAD commands.β[0m
β[37mβ[0m
β[37m This sends the response code and MIME headers.β[0m
β[37mβ[0m
β[37m Return value is either a file object (which has to be copiedβ[0m
β[37m to the outputfile by the caller unless the command was HEAD,β[0m
β[37m and must be closed by the caller under all circumstances), orβ[0m
β[37m None, in which case the caller has nothing further to do.β[0m
β[37mβ[0m
β[37m """β[0m
β[37m path = self.translate_path(self.path)β[0m
β[37m f = Noneβ[0m
β[37m if os.path.isdir(path):β[0m
β[37m parts = urllib.parse.urlsplit(self.path)β[0m
β[37m if not parts.path.endswith(('/', '%2f', '%2F')):β[0m
β[37m # redirect browser - doing basically what apache doesβ[0m
β[37m self.send_response(HTTPStatus.MOVED_PERMANENTLY)β[0m
β[37m new_parts = (parts[0], parts[1], parts[2] + '/',β[0m
β[37m parts[3], parts[4])β[0m
β[37m new_url = urllib.parse.urlunsplit(new_parts)β[0m
-- missing expected lines --
β[38;5;208m """Common code for GET and HEAD commands.β[0m
[7/11] list_directory β prompt 50,541 chars, waiting on model...
response: 677 chars in 40.8s
=== list_directory [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""Helper to produce a directory listing (absent index.html).β[0m
β[37mβ[0m
β[37m Return value is either a file object, or None (indicating anβ[0m
β[37m error). In either case, the headers are sent, making theβ[0m
β[37m interface the same as for send_head().β[0m
β[37mβ[0m
β[37m """β[0m
β[37m try:β[0m
β[37m list = os.listdir(path)β[0m
β[37m except OSError:β[0m
β[37m self.send_error(β[0m
β[37m HTTPStatus.NOT_FOUND,β[0m
β[37m "No permission to list directory")β[0m
β[37m return Noneβ[0m
β[37m list.sort(key=lambda a: a.lower())β[0m
β[37m r = []β[0m
β[37m displaypath = self.pathβ[0m
β[37m displaypath = displaypath.split('#', 1)[0]β[0m
β[37m displaypath = displaypath.split('?', 1)[0]β[0m
β[37m try:β[0m
-- missing expected lines --
β[38;5;208m """Helper to produce a directory listing (absent index.html).β[0m
[8/11] translate_path β prompt 50,541 chars, waiting on model...
response: 778 chars in 57.7s
=== translate_path [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""Translate a /-separated PATH to the local filename syntax.β[0m
β[37mβ[0m
β[37m Components that mean special things to the local file systemβ[0m
β[37m (e.g. drive or directory names) are ignored. (XXX They shouldβ[0m
β[37m probably be diagnosed.)β[0m
β[37mβ[0m
β[37m """β[0m
β[37m # abandon query parametersβ[0m
β[37m path = path.split('#', 1)[0]β[0m
β[37m path = path.split('?', 1)[0]β[0m
β[37m # Don't forget explicit trailing slash when normalizing. Issue17324β[0m
β[37m try:β[0m
β[37m path = urllib.parse.unquote(path, errors='surrogatepass')β[0m
β[37m except UnicodeDecodeError:β[0m
β[37m path = urllib.parse.unquote(path)β[0m
β[37m trailing_slash = path.endswith('/')β[0m
β[37m path = posixpath.normpath(path)β[0m
β[37m words = path.split('/')β[0m
β[37m words = filter(None, words)β[0m
β[37m path = self.directoryβ[0m
-- missing expected lines --
β[38;5;208m """Translate a /-separated PATH to the local filename syntax.β[0m
[9/11] guess_type β prompt 50,529 chars, waiting on model...
response: 737 chars in 57.2s
=== guess_type [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""Guess the type of a file.β[0m
β[37mβ[0m
β[37m Argument is a PATH (a filename).β[0m
β[37mβ[0m
β[37m Return value is a string of the form type/subtype,β[0m
β[37m usable for a MIME Content-type header.β[0m
β[37mβ[0m
β[37m The default implementation looks the file's extensionβ[0m
β[37m up in the table self.extensions_map, using application/octet-streamβ[0m
β[37m as a default; however it would be permissible (ifβ[0m
β[37m slow) to look inside the data to make a better guess.β[0m
β[37mβ[0m
β[37m """β[0m
β[37m base, ext = posixpath.splitext(path)β[0m
β[37m if ext in self.extensions_map:β[0m
β[37m return self.extensions_map[ext]β[0m
β[37m ext = ext.lower()β[0m
β[37m if ext in self.extensions_map:β[0m
β[37m return self.extensions_map[ext]β[0m
β[37m guess, _ = mimetypes.guess_file_type(path)β[0m
-- missing expected lines --
β[38;5;208m """Guess the type of a file.β[0m
[10/11] is_cgi β prompt 50,517 chars, waiting on model...
response: 914 chars in 84.8s
=== is_cgi [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""Test whether self.path corresponds to a CGI script.β[0m
β[37mβ[0m
β[37m Returns True and updates the cgi_info attribute to the tupleβ[0m
β[37m (dir, rest) if self.path requires running a CGI script.β[0m
β[37m Returns False otherwise.β[0m
β[37mβ[0m
β[37m If any exception is raised, the caller should assume thatβ[0m
β[37m self.path was rejected as invalid and act accordingly.β[0m
β[37mβ[0m
β[37m The default implementation tests whether the normalized urlβ[0m
β[37m path begins with one of the strings in self.cgi_directoriesβ[0m
β[37m (and the next character is a '/' or the end of the string).β[0m
β[37mβ[0m
β[37m """β[0m
β[37m collapsed_path = _url_collapse_path(self.path)β[0m
β[37m dir_sep = collapsed_path.find('/', 1)β[0m
β[37m while dir_sep > 0 and not collapsed_path[:dir_sep] in self.cgi_directories:β[0m
β[37m dir_sep = collapsed_path.find('/', dir_sep+1)β[0m
β[37m if dir_sep > 0:β[0m
β[37m head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:]β[0m
-- missing expected lines --
β[38;5;208m """Test whether self.path corresponds to a CGI script.β[0m
[11/11] run_cgi β prompt 50,520 chars, waiting on model...
response: 685 chars in 63.5s
=== run_cgi [β[32mPASSβ[0m] matched=19/20 hallucinated=1 bonus=0 ===
-- model output --
β[33m"""Execute a CGI script."""β[0m
β[37m dir, rest = self.cgi_infoβ[0m
β[37m path = dir + '/' + restβ[0m
β[37m i = path.find('/', len(dir)+1)β[0m
β[37m while i >= 0:β[0m
β[37m nextdir = path[:i]β[0m
β[37m nextrest = path[i+1:]β[0m
β[37mβ[0m
β[37m scriptdir = self.translate_path(nextdir)β[0m
β[37m if os.path.isdir(scriptdir):β[0m
β[37m dir, rest = nextdir, nextrestβ[0m
β[37m i = path.find('/', len(dir)+1)β[0m
β[37m else:β[0m
β[37m breakβ[0m
β[37mβ[0m
β[37m # find an explicit query string, if present.β[0m
β[37m rest, _, query = rest.partition('?')β[0m
β[37mβ[0m
β[37m # dissect the part after the directory name into a script name &β[0m
β[37m # a possible additional path, to be stored in PATH_INFO.β[0m
-- missing expected lines --
β[38;5;208m """Execute a CGI script."""β[0m
β[1m=== SUMMARY ===β[0m
Pass: 11/11
Primary lines matched: 209/220
Hallucinated lines: 11
Bonus (extra correct): 0
per-function:
β[32mββ[0m _url_collapse_path matched=19/20 halluc= 1 bonus= 0
β[32mββ[0m parse_request matched=19/20 halluc= 1 bonus= 0
β[32mββ[0m handle_one_request matched=19/20 halluc= 1 bonus= 0
β[32mββ[0m send_error matched=19/20 halluc= 1 bonus= 0
β[32mββ[0m log_message matched=19/20 halluc= 1 bonus= 0
β[32mββ[0m send_head matched=19/20 halluc= 1 bonus= 0
β[32mββ[0m list_directory matched=19/20 halluc= 1 bonus= 0
β[32mββ[0m translate_path matched=19/20 halluc= 1 bonus= 0
β[32mββ[0m guess_type matched=19/20 halluc= 1 bonus= 0
β[32mββ[0m is_cgi matched=19/20 halluc= 1 bonus= 0
β[32mββ[0m run_cgi matched=19/20 halluc= 1 bonus= 0
halluc= 1 for XL version are false as this simply wrong indentation, still strange as Q8 version had less of this problem. Seems it still can be optimized.
