CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-niquests

Niquests is a simple, yet elegant, HTTP library that is a drop-in replacement for Requests, which is under feature freeze.

Pending
Overview
Eval results
Files

models.mddocs/

Request and Response Models

Core data structures for representing HTTP requests and responses. These classes provide access to all HTTP components including headers, body content, status codes, and metadata. They form the foundation of all HTTP operations in niquests.

Capabilities

Request Class

A user-created Request object used to represent an HTTP request before it's prepared for transmission.

class Request:
    """
    A user-created Request object.
    
    Used to prepare a PreparedRequest, which is sent to the server.
    Contains the high-level request information provided by the user.
    """
    
    def __init__(
        self,
        method: HttpMethodType,
        url: str,
        *,
        headers: HeadersType | None = None,
        files: MultiPartFilesType | MultiPartFilesAltType | None = None,
        data: BodyType | None = None,
        json: Any | None = None,
        params: QueryParameterType | None = None,
        auth: HttpAuthenticationType | None = None,
        cookies: CookiesType | None = None,
        hooks: HookType[PreparedRequest | Response] | None = None,
    ):
        """
        Initialize a new Request object.
        
        Args:
            method: HTTP method (GET, POST, PUT, etc.)
            url: Target URL
            headers: HTTP headers dictionary
            files: Files for multipart upload
            data: Request body data
            json: JSON data to serialize
            params: Query parameters
            auth: Authentication credentials
            cookies: Cookies to include
            hooks: Request/response hooks
        """
    
    def prepare(self) -> PreparedRequest:
        """
        Prepare the Request for transmission.
        
        Returns:
            PreparedRequest ready for sending
        """
    
    # Instance attributes
    method: HttpMethodType
    url: str
    headers: HeadersType | None
    files: MultiPartFilesType | MultiPartFilesAltType | None
    data: BodyType | None
    json: Any | None
    params: QueryParameterType | None
    auth: HttpAuthenticationType | None
    cookies: CookiesType | None
    hooks: HookType | None

PreparedRequest Class

The fully prepared request object containing the exact bytes that will be sent to the server.

class PreparedRequest:
    """
    The fully mutable PreparedRequest object.
    
    Contains the exact bytes that will be sent to the server.
    Generated from a Request object and should not be instantiated manually.
    """
    
    def __init__(self):
        """Initialize a new PreparedRequest."""
    
    def prepare(
        self,
        method: HttpMethodType | None = None,
        url: str | None = None,
        files: MultiPartFilesType | MultiPartFilesAltType | None = None,
        data: BodyType | None = None,
        json: Any | None = None,
        headers: HeadersType | None = None,
        params: QueryParameterType | None = None,
        auth: HttpAuthenticationType | None = None,
        cookies: CookiesType | None = None,
        hooks: HookType[PreparedRequest | Response] | None = None,
    ):
        """
        Prepare all aspects of the request.
        
        Args:
            method: HTTP method
            url: Target URL
            files: Files for upload
            data: Request body
            json: JSON data
            headers: HTTP headers
            params: Query parameters
            auth: Authentication
            cookies: Cookies
            hooks: Lifecycle hooks
        """
    
    def copy(self) -> PreparedRequest:
        """
        Copy the PreparedRequest.
        
        Returns:
            New PreparedRequest instance with same data
        """
    
    # Instance attributes
    method: HttpMethodType | None
    url: str | None
    headers: HeadersType | None
    body: bytes | None
    hooks: HookType | None
    path_url: str | None

Response Class

The Response object containing a server's response to an HTTP request.

class Response:
    """
    The Response object containing a server's response to an HTTP request.
    
    Provides access to response data, headers, status code, and metadata.
    """
    
    def __init__(self):
        """Initialize a new Response object."""
    
    def __enter__(self) -> Response:
        """Enter context manager for response."""
        return self
    
    def __exit__(self, *args):
        """Exit context manager and close response."""
        self.close()
    
    @property
    def content(self) -> bytes:
        """
        Content of the response, in bytes.
        
        Returns:
            Response body as bytes
        """
    
    @property
    def text(self) -> str:
        """
        Content of the response, in unicode.
        
        If Response.encoding is None, encoding will be guessed using
        charset-normalizer or chardet.
        
        Returns:
            Response body as string
        """
    
    @property
    def encoding(self) -> str | None:
        """
        Encoding to decode with when accessing text.
        
        Returns:
            Character encoding name or None
        """
    
    @encoding.setter
    def encoding(self, value: str):
        """Set the encoding for text decoding."""
    
    def json(self, **kwargs) -> Any:
        """
        Return the json-encoded content of a response, if any.
        
        Args:
            **kwargs: Optional arguments to pass to json.loads()
            
        Returns:
            JSON-decoded response content
            
        Raises:
            JSONDecodeError: If response content is not valid JSON
        """
    
    @property
    def links(self) -> dict:
        """
        Returns the parsed header links of the response, if any.
        
        Returns:
            Dictionary of link relations to links
        """
    
    @property
    def ok(self) -> bool:
        """
        Returns True if status_code is less than 400, False otherwise.
        
        Returns:
            True for successful responses (status < 400)
        """
    
    @property
    def is_redirect(self) -> bool:
        """
        True if this Response is a well-formed HTTP redirect.
        
        Returns:
            True if response is a redirect
        """
    
    @property  
    def is_permanent_redirect(self) -> bool:
        """
        True if this Response is a permanent redirect.
        
        Returns:
            True if response is a permanent redirect (301, 308)
        """
    
    def iter_content(self, chunk_size: int = 1, decode_unicode: bool = False):
        """
        Iterate over the response data in chunks.
        
        Args:
            chunk_size: Size of each chunk in bytes
            decode_unicode: Whether to decode chunks to unicode
            
        Yields:
            Raw bytes or decoded strings if decode_unicode=True
        """
    
    def iter_lines(self, chunk_size: int = 512, decode_unicode: bool = False, delimiter: str | None = None):
        """
        Iterate over the response data one line at a time.
        
        Args:
            chunk_size: Size of chunks to read
            decode_unicode: Whether to decode lines to unicode
            delimiter: Line delimiter to use
            
        Yields:
            Lines from the response content
        """
    
    def raise_for_status(self):
        """
        Raise HTTPError if one occurred.
        
        Raises:
            HTTPError: If the response status indicates an error
        """
    
    def close(self):
        """
        Release the connection back to the pool.
        
        Once this method has been called the underlying raw object
        must not be accessed again.
        """
    
    # Instance attributes
    status_code: int  # HTTP status code
    headers: HeadersType  # Response headers
    raw: BaseHTTPResponse | None  # Raw response object
    url: str  # Final URL after redirects
    encoding: str | None  # Character encoding
    history: list[Response]  # List of redirect responses
    reason: str  # HTTP status reason phrase
    cookies: RequestsCookieJar  # Response cookies
    elapsed: datetime.timedelta  # Time taken for request
    request: PreparedRequest  # The request that generated this response
    connection: ConnectionInfo  # Connection information
    extensions: dict  # Protocol extensions (WebSocket, etc.)

AsyncResponse Class

Async version of the Response class for asynchronous HTTP operations.

class AsyncResponse(Response):
    """
    The AsyncResponse object for asynchronous HTTP requests.
    
    Inherits from Response and provides async methods for content access.
    """
    
    async def aclose(self):
        """
        Asynchronously release the connection back to the pool.
        """
    
    def close(self):
        """
        Synchronously close the response (calls aclose internally).
        """
    
    async def json(self, **kwargs) -> Any:
        """
        Asynchronously return the json-encoded content of the response.
        
        Args:
            **kwargs: Optional arguments to pass to json.loads()
            
        Returns:
            JSON-decoded response content
            
        Raises:
            JSONDecodeError: If response content is not valid JSON
        """
    
    @property
    async def content(self) -> bytes:
        """
        Asynchronously access content of the response, in bytes.
        
        Returns:
            Response body as bytes
        """
    
    @property
    async def text(self) -> str:
        """
        Asynchronously access content of the response, in unicode.
        
        Returns:
            Response body as string
        """
    
    # Async context manager support
    async def __aenter__(self) -> AsyncResponse:
        """Enter async context manager."""
        return self
    
    async def __aexit__(self, *args):
        """Exit async context manager and close response."""
        await self.aclose()

Usage Examples

Creating and Using Requests

import niquests

# Create a Request object
request = niquests.Request(
    method='POST',
    url='https://api.example.com/users',
    json={'name': 'John Doe', 'email': 'john@example.com'},
    headers={'Content-Type': 'application/json'}
)

# Prepare the request
prepared = request.prepare()

# Send using a session
with niquests.Session() as session:
    response = session.send(prepared)
    print(response.status_code)

Working with Responses

import niquests

# Make a request and get response
response = niquests.get('https://api.example.com/users')

# Access response properties
print(f"Status Code: {response.status_code}")
print(f"Status Reason: {response.reason}")
print(f"Content Type: {response.headers.get('content-type')}")
print(f"Response Size: {len(response.content)} bytes")

# Check if request was successful
if response.status_code == 200:
    # Parse JSON response
    users = response.json()
    print(f"Found {len(users)} users")
else:
    print(f"Request failed: {response.status_code}")

# Raise exception for HTTP errors
try:
    response.raise_for_status()
    data = response.json()
except niquests.HTTPError as e:
    print(f"HTTP Error: {e}")
except niquests.JSONDecodeError as e:
    print(f"JSON Decode Error: {e}")

Response Content Handling

# Text content with automatic encoding detection
response = niquests.get('https://example.com/page.html')
html_content = response.text

# Binary content
response = niquests.get('https://example.com/image.jpg')
image_bytes = response.content

# Save binary content to file
with open('downloaded_image.jpg', 'wb') as f:
    f.write(response.content)

# Streaming large responses
response = niquests.get('https://example.com/large-file.zip', stream=True)
with open('large-file.zip', 'wb') as f:
    for chunk in response.iter_content(chunk_size=8192):
        f.write(chunk)

Async Response Handling

import asyncio
import niquests

async def fetch_and_process():
    response = await niquests.aget('https://api.example.com/data')
    
    # Async context manager automatically closes response
    async with response:
        # Async content access
        json_data = await response.json()
        text_content = await response.text
        binary_content = await response.content
        
        return json_data

# Run async function
data = asyncio.run(fetch_and_process())

Response Metadata

response = niquests.get('https://httpbin.org/get')

# Connection information
print(f"HTTP Version: {response.connection.http_version}")
print(f"Remote Address: {response.connection.destination_address}")

# Timing information
print(f"Request took: {response.elapsed.total_seconds()} seconds")

# Redirect history
if response.history:
    print(f"Request was redirected {len(response.history)} times")
    for i, redirect in enumerate(response.history):
        print(f"  Redirect {i+1}: {redirect.status_code} -> {redirect.url}")

# Cookie handling
if response.cookies:
    print("Response cookies:")
    for cookie in response.cookies:
        print(f"  {cookie.name}: {cookie.value}")

# Link headers (for pagination, etc.)
if response.links:
    print("Link headers:")
    for rel, link in response.links.items():
        print(f"  {rel}: {link['url']}")

Error Handling with Models

import niquests

try:
    response = niquests.get('https://api.example.com/protected', timeout=5.0)
    response.raise_for_status()  # Raise HTTPError for bad status codes
    
    data = response.json()
    print("Success:", data)
    
except niquests.ConnectionError:
    print("Failed to connect to the server")
except niquests.Timeout:
    print("Request timed out")
except niquests.HTTPError as e:
    print(f"HTTP error {e.response.status_code}: {e.response.reason}")
    # Can still access response data even for errors
    if e.response.headers.get('content-type') == 'application/json':
        error_details = e.response.json()
        print(f"Error details: {error_details}")
except niquests.JSONDecodeError:
    print("Response is not valid JSON")
    print("Raw content:", response.text)

Advanced Features

Custom Response Processing

class CustomResponse(niquests.Response):
    """Custom response class with additional methods."""
    
    def is_json(self) -> bool:
        """Check if response content type is JSON."""
        content_type = self.headers.get('content-type', '')
        return 'application/json' in content_type.lower()
    
    def safe_json(self, default=None):
        """Safely parse JSON, returning default if parsing fails."""
        if self.is_json():
            try:
                return self.json()
            except niquests.JSONDecodeError:
                pass
        return default

# Note: Custom response classes would need to be used with custom adapters

Response Streaming

def download_large_file(url, filename):
    """Download large file with progress tracking."""
    response = niquests.get(url, stream=True)
    response.raise_for_status()
    
    total_size = int(response.headers.get('content-length', 0))
    downloaded = 0
    
    with open(filename, 'wb') as f:
        for chunk in response.iter_content(chunk_size=8192):
            if chunk:  # Filter out keep-alive chunks
                f.write(chunk)
                downloaded += len(chunk)
                
                if total_size > 0:
                    progress = (downloaded / total_size) * 100
                    print(f"Downloaded: {progress:.1f}%")
    
    print(f"Download complete: {filename}")

Type Definitions

# Base HTTP types
HttpMethodType = Literal["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]
HeadersType = Union[dict, Headers, CaseInsensitiveDict]
CookiesType = Union[dict, RequestsCookieJar]

# Request body types
BodyType = Union[str, bytes, dict, list, IOBase]
AsyncBodyType = Union[str, bytes, dict, list, IOBase, AsyncIterable[bytes]]

# Multipart file types
MultiPartFilesType = dict
MultiPartFilesAltType = dict

# Query parameters
QueryParameterType = Union[dict, list, bytes]

# Authentication types
HttpAuthenticationType = Union[Tuple[str, str], HTTPBasicAuth, BearerTokenAuth]
AsyncHttpAuthenticationType = Union[HttpAuthenticationType, Callable]

# Hook types
HookType = dict

# Connection info
ConnectionInfo = object  # Detailed connection metadata

Install with Tessl CLI

npx tessl i tessl/pypi-niquests

docs

advanced-features.md

async-requests.md

exceptions.md

index.md

models.md

sessions.md

sync-requests.md

tile.json