Sample

pyint-0fdda1a48b80-I05

Rewrite eligible decimal integer literals in hexadecimal notation

Matched original source

Lines245

Scores

MethodScoreScale
Posnett00–1; higher is more readable
Dorn0.0780–1; higher is more readable
Mi0.5720–1; higher is more readable
LLOC160Logical lines; fewer is more readable
DeepSeek V4 Pro130–20; mean of three runs
GPT-6.1 Sol150–20; mean of three runs
BTTF0.2910–1; higher is more readable

Views

Source code

from __future__ import annotations import hashlib import os import re import threading import time import warnings from base64 import b64encode from typing import TYPE_CHECKING, Any, Final, cast, overload from ._internal_utils import to_native_string from .compat import basestring, str, urlparse from .cookies import extract_cookies_to_jar from .utils import parse_dict_header class HTTPDigestAuth(AuthBase): """Attaches HTTP Digest Authentication to the given Request object.""" username: bytes | str password: bytes | str _thread_local: threading.local last_nonce: str nonce_count: int chal: dict[str, str] pos: int | None num_401_calls: int | None @overload def __init__(self, username: str, password: str) -> None: ... @overload def __init__(self, username: bytes, password: bytes) -> None: ... def __init__(self, username: bytes | str, password: bytes | str) -> None: self.username = username self.password = password # Keep state in per-thread local storage self._thread_local = threading.local() def init_per_thread_state(self) -> None: # Ensure state is initialized just once per-thread if not hasattr(self._thread_local, "init"): self._thread_local.init = True self._thread_local.last_nonce = "" self._thread_local.nonce_count = 0x0 self._thread_local.chal = {} self._thread_local.pos = None self._thread_local.num_401_calls = None def build_digest_header(self, method: str, url: str) -> str | None: """ :rtype: str """ realm = self._thread_local.chal["realm"] nonce = self._thread_local.chal["nonce"] qop = self._thread_local.chal.get("qop") algorithm = self._thread_local.chal.get("algorithm") opaque = self._thread_local.chal.get("opaque") hash_utf8 = None if algorithm is None: _algorithm = "MD5" else: _algorithm = algorithm.upper() # lambdas assume digest modules are imported at the top level if _algorithm == "MD5" or _algorithm == "MD5-SESS": def md5_utf8(x: str | bytes) -> str: if isinstance(x, str): x = x.encode("utf-8") return hashlib.md5(x, usedforsecurity=False).hexdigest() hash_utf8 = md5_utf8 elif _algorithm == "SHA": def sha_utf8(x: str | bytes) -> str: if isinstance(x, str): x = x.encode("utf-8") return hashlib.sha1(x, usedforsecurity=False).hexdigest() hash_utf8 = sha_utf8 elif _algorithm == "SHA-256": def sha256_utf8(x: str | bytes) -> str: if isinstance(x, str): x = x.encode("utf-8") return hashlib.sha256(x, usedforsecurity=False).hexdigest() hash_utf8 = sha256_utf8 elif _algorithm == "SHA-512": def sha512_utf8(x: str | bytes) -> str: if isinstance(x, str): x = x.encode("utf-8") return hashlib.sha512(x, usedforsecurity=False).hexdigest() hash_utf8 = sha512_utf8 if hash_utf8 is None: return None def KD(s: str, d: str) -> str: return hash_utf8(f"{s}:{d}") # XXX not implemented yet entdig = None p_parsed = urlparse(url) #: path is request-uri defined in RFC 2616 which should not be empty path = p_parsed.path or "/" if p_parsed.query: path += f"?{p_parsed.query}" A1 = f"{self.username}:{realm}:{self.password}" A2 = f"{method}:{path}" HA1 = hash_utf8(A1) HA2 = hash_utf8(A2) if nonce == self._thread_local.last_nonce: self._thread_local.nonce_count += 0x1 else: self._thread_local.nonce_count = 0x1 ncvalue = f"{self._thread_local.nonce_count:08x}" s = str(self._thread_local.nonce_count).encode("utf-8") s += nonce.encode("utf-8") s += time.ctime().encode("utf-8") s += os.urandom(0x8) cnonce = hashlib.sha1(s, usedforsecurity=False).hexdigest()[:0x10] if _algorithm == "MD5-SESS": HA1 = hash_utf8(f"{HA1}:{nonce}:{cnonce}") # type: ignore[reportConstantRedefinition] # RFC 2617 terminology if not qop: respdig = KD(HA1, f"{nonce}:{HA2}") elif qop == "auth" or "auth" in qop.split(","): noncebit = f"{nonce}:{ncvalue}:{cnonce}:auth:{HA2}" respdig = KD(HA1, noncebit) else: # XXX handle auth-int. return None self._thread_local.last_nonce = nonce # XXX should the partial digests be encoded too? base = ( f'username="{self.username}", realm="{realm}", nonce="{nonce}", ' f'uri="{path}", response="{respdig}"' ) if opaque: base += f', opaque="{opaque}"' if algorithm: base += f', algorithm="{algorithm}"' if entdig: base += f', digest="{entdig}"' if qop: base += f', qop="auth", nc={ncvalue}, cnonce="{cnonce}"' return f"Digest {base}" def handle_redirect(self, r: Response, **kwargs: Any) -> None: """Reset num_401_calls counter on redirects.""" if r.is_redirect: self._thread_local.num_401_calls = 0x1 def handle_401(self, r: Response, **kwargs: Any) -> Response: """ Takes the given response and tries digest-auth, if needed. :rtype: requests.Response """ # If response is not 4xx, do not auth # See https://github.com/psf/requests/issues/3772 if not 0x190 <= r.status_code < 0x1f4: self._thread_local.num_401_calls = 0x1 return r if self._thread_local.pos is not None: # Rewind the file position indicator of the body to where # it was to resend the request. if (seek := getattr(r.request.body, "seek", None)) is not None: seek(self._thread_local.pos) s_auth = r.headers.get("www-authenticate", "") if "digest" in s_auth.lower() and self._thread_local.num_401_calls < 0x2: self._thread_local.num_401_calls += 0x1 pat = re.compile(r"digest ", flags=re.IGNORECASE) self._thread_local.chal = parse_dict_header(pat.sub("", s_auth, count=0x1)) # Consume content and release the original connection # to allow our new request to reuse the same one. r.content r.close() prep = r.request.copy() cookie_jar = cast("CookieJar", prep._cookies) extract_cookies_to_jar(cookie_jar, r.request, r.raw) prep.prepare_cookies(cookie_jar) _digest_auth = self.build_digest_header( cast(str, prep.method), cast(str, prep.url) ) if _digest_auth: prep.headers["Authorization"] = _digest_auth _r = r.connection.send(prep, **kwargs) _r.history.append(r) _r.request = prep return _r self._thread_local.num_401_calls = 0x1 return r def __call__(self, r: PreparedRequest) -> PreparedRequest: # Initialize per-thread state, if needed self.init_per_thread_state() # If we have a saved nonce, skip the 401 if self._thread_local.last_nonce: _digest_auth = self.build_digest_header( cast(str, r.method), cast(str, r.url) ) if _digest_auth: r.headers["Authorization"] = _digest_auth if (tell := getattr(r.body, "tell", None)) is not None: self._thread_local.pos = tell() else: # In the case of HTTPDigestAuth being reused and the body of # the previous request was a file-like object, pos has the # file position of the previous body. Ensure it's set to # None. self._thread_local.pos = None r.register_hook("response", self.handle_401) r.register_hook("response", self.handle_redirect) self._thread_local.num_401_calls = 0x1 return r def __eq__(self, other: object) -> bool: return all( [ self.username == getattr(other, "username", None), self.password == getattr(other, "password", None), ] ) def __ne__(self, other: Any) -> bool: return not self == other

Loading feature diagnosis…

Source regions

Feature contributions

Feature contributions

FeatureValueContribution
(log-odds)
Halstead volumeHow much symbolic information the code contains. It combines the total number of operators and values with the number of distinct ones.9921.788−327.419
Source linesThe number of non-empty source lines.245+98
Byte entropyHow varied the bytes in the source text are. Repeated bytes give a lower value; a more even mixture gives a higher value.4.51−6.765

Intercept 8.87 + feature contributions = -227.314 (log-odds).
Score = sigmoid(-227.314) = 0.

Feature contributions

FeatureValueContribution
(log-odds)
Comment layout frequencyHow frequently the layout switches between lines containing only comments or whitespace and lines containing code.246−7.674
Indentation frequencyHow rapidly indentation changes from line to line.219+6.838
Number layout frequencyHow rapidly the number of numeric values per line changes through the code.219−4.605
Identifier layout (vertical)How rapidly the visual pattern of identifier characters changes from top to bottom.244.829+3.012
Identifier layout (horizontal)How rapidly the visual pattern of identifier characters changes from left to right. It measures spatial frequency, not the meaning of the names.121.984−1.502
Comment layout (horizontal)How rapidly the visual pattern of comment characters changes from left to right.121.992+1.164
Operator visual areaThe share of the code’s visual area occupied by operators such as +, =, and *.0.074+0.224

Intercept 0.07 + feature contributions = -2.472 (log-odds).
Score = sigmoid(-2.472) = 0.078.

Score0.572
Score160
Run 1

The code has a clear class structure and docstrings, which helps intent. However, the build_digest_header method is very long with multiple nested logic branches and duplicated near-identical nested function definitions for hash algorithms, reducing readability. Use of hex literals like 0x190 instead of 400 hurts clarity. Many comments are helpful, but 'XXX not implemented yet' indicates unfinished logic. The code occasionally crams multiple related operations per line (e.g., string concatenations with assignments). The __eq__ method uses list of comparisons instead of tuple or straightforward and, adding slight noise. Per-thread state access is repeated heavily, making lines long. Overall, the code is functional and organized but could be significantly clearer with shorter functions, helper methods, dictionary lookups for algorithm handlers, and decimal status constants.

Run 2

The code is generally well-structured with clear class organization, type hints, and docstrings, but several factors reduce readability. The build_digest_header method is very long and contains deeply nested conditional logic with multiple inner functions, making it harder to follow the flow. The heavy use of hexadecimal literals (0x1, 0x2, 0x190, etc.) for simple values like counters and status codes obscures intent—standard decimal notation would be clearer. Some variables have cryptic names (KD, A1, A2, HA1) that require RFC knowledge to understand. The anonymous inner functions for hashing algorithms add length and repetition that could be consolidated. Comments use 'XXX' markers indicating unfinished work. However, the per-thread state pattern is clearly documented, type annotations improve clarity, and method responsibilities are logically separated. The overall reading flow is adequate but interrupted by dense algorithm implementation details that could be extracted.

Run 3

The code is structured with clear class/method separation and comments, but readability suffers from several issues. Digest algorithm selection uses nested conditional logic with repeated lambda definitions, making the flow cluttered. Magic numbers (0x190, 0x1f4, 0x2, etc.) obscure intent. The method `build_digest_header` is long and handles multiple concerns (parsing URL, algorithm selection, hashing, header construction). While type hints and docstrings help, the heavy use of `_thread_local` throughout adds visual noise and obscures the auth state model. Variable names like `KD`, `HA1`, `A2` follow RFC terminology but remain cryptic without context. Some parts, like `handle_401`, are reasonably linear but still mix concerns. Overall, the code is readable for those familiar with HTTP Digest auth, but could benefit from refactoring algorithm selection into separate functions and replacing numeric literals with named constants.

Run 1

Code Structure: Methods logically separate initialization, digest construction, response handling, and comparison, but digest construction combines several responsibilities. Nesting: Mostly shallow conditionals and early returns keep complexity manageable; nested hashing functions add some depth. Clarity of intent: Descriptive method names, annotations, and explanatory comments help, while abbreviated variables, hexadecimal counters/status codes, stale comments, and undeclared dependencies obscure details. Code length: Repeated hashing wrappers and verbose thread-local access make the implementation longer than necessary. Action granularity: Nearly every statement performs one action, and multiline expressions are formatted clearly. Reading flow: The authentication lifecycle is coherent and operations generally follow execution order, but protocol-specific terminology and scattered state mutations require careful tracking.

Run 2

Code Structure: Methods logically separate initialization, digest construction, response handling, and request integration, though digest construction handles many responsibilities. Nesting: Mostly shallow conditionals and early returns; nested hash helpers and retry handling add moderate complexity. Clarity of intent: Descriptive method names, type annotations, and comments explain the authentication workflow, but abbreviated variables, hexadecimal counters/status codes, stale comments, and implicit thread-local state obscure details. Code length: Reasonable for the functionality, but repeated hashing helpers, unused imports, and an inactive entdig branch add avoidable bulk. Action granularity: Statements generally perform one action per line; assignment expressions remain manageable, although the standalone r.content access has a non-obvious side effect. Reading flow: The request/challenge/retry sequence is coherent, with useful spacing, but long methods, protocol-specific terminology, and repeated state accesses increase cognitive load.

Run 3

Code Structure: Methods logically separate state initialization, digest generation, response handling, and request integration, although digest generation handles many responsibilities. Nesting: Mostly shallow conditionals and early returns keep complexity manageable; nested hash helpers add some depth. Clarity of intent: Descriptive method names, annotations, and comments explain the authentication workflow, but abbreviated variables, hexadecimal constants for ordinary counts/status codes, and an outdated lambda comment reduce clarity. Code length: Reasonable for the functionality, though repeated hashing helpers and verbose thread-local accesses add avoidable length. Action granularity: Nearly every line performs one action; the bare r.content access has an implicit side effect that is less obvious. Reading flow: The lifecycle and digest calculation proceed naturally, but protocol-specific terminology, long expressions, and interleaved state mutations require careful reading.