CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pycares

Python interface for c-ares asynchronous DNS library

Pending
Overview
Eval results
Files

utilities.mddocs/

Utility Functions

String encoding and domain name processing utilities for handling international domain names, proper ASCII encoding, and data conversion within pycares operations.

Capabilities

String Encoding

Convert various string and bytes types to appropriate formats for DNS operations.

def ascii_bytes(data):
    """
    Convert string or bytes data to ASCII bytes.
    
    Args:
        data: Union[str, bytes] - Input data to convert
        
    Returns:
        bytes: ASCII-encoded bytes
        
    Raises:
        TypeError: If data is neither str nor bytes
    """

def maybe_str(data):
    """
    Convert bytes to string if possible, otherwise return as-is.
    
    Attempts to decode bytes data to ASCII string. If decoding fails,
    returns the original bytes object.
    
    Args:
        data: Union[str, bytes] - Input data to convert
        
    Returns:
        Union[str, bytes]: String if decodable to ASCII, otherwise bytes
        
    Raises:
        TypeError: If data is neither str nor bytes
    """

Usage Example:

import pycares

# Convert string to ASCII bytes
hostname_bytes = pycares.ascii_bytes("example.com")
print(hostname_bytes)  # b'example.com'

# Convert bytes to string if possible
result = pycares.maybe_str(b"example.com")
print(result)  # 'example.com'

# Binary data stays as bytes
binary_data = b'\x00\x01\x02'
result = pycares.maybe_str(binary_data)
print(type(result))  # <class 'bytes'>

Domain Name Processing

Process domain names for DNS queries, including support for internationalized domain names (IDNA).

def parse_name(name):
    """
    Parse and encode domain name for DNS queries.
    
    Handles both ASCII and internationalized domain names. For ASCII names,
    performs direct encoding. For international domain names, uses IDNA 2008
    encoding if the idna package is available, otherwise falls back to
    built-in IDNA 2003 encoding.
    
    Args:
        name: Union[str, bytes] - Domain name to parse
        
    Returns:
        bytes: Properly encoded domain name for DNS queries
        
    Raises:
        TypeError: If name is neither str nor bytes
        RuntimeError: If domain part exceeds 253 characters
    """

Usage Example:

import pycares

# ASCII domain name
ascii_domain = pycares.parse_name("example.com")
print(ascii_domain)  # b'example.com'

# International domain name (requires idna package for IDNA 2008)
try:
    intl_domain = pycares.parse_name("例え.テスト")
    print(intl_domain)  # Encoded bytes representation
except RuntimeError as e:
    print(f"Domain name too long: {e}")

# Bytes input passes through
bytes_domain = pycares.parse_name(b"example.org")
print(bytes_domain)  # b'example.org'

IDNA Support

pycares provides enhanced internationalized domain name support when the optional idna package is installed:

# Install with IDNA 2008 support
# pip install pycares[idna]

IDNA 2008 vs IDNA 2003

  • With idna package: Uses modern IDNA 2008 standard for better Unicode support
  • Without idna package: Falls back to Python's built-in IDNA 2003 codec
  • ASCII domains: No difference, processed efficiently in both cases

Domain Length Limits

The parse_name function enforces DNS domain length limits:

  • Individual labels (parts between dots) must be ≤ 253 characters after encoding
  • Total domain name length should comply with DNS standards

Example with Error Handling:

import pycares

def safe_parse_name(domain):
    """Safely parse domain name with error handling."""
    try:
        return pycares.parse_name(domain)
    except TypeError:
        print(f"Invalid domain type: {type(domain)}")
        return None
    except RuntimeError as e:
        print(f"Domain name error: {e}")
        return None

# Test with various inputs
domains = [
    "example.com",           # ASCII domain
    "例え.テスト",             # International domain  
    b"binary.domain",        # Bytes input
    123,                     # Invalid type
    "a" * 300 + ".com"       # Too long
]

for domain in domains:
    result = safe_parse_name(domain)
    if result:
        print(f"Parsed: {domain} -> {result}")
    else:
        print(f"Failed to parse: {domain}")

Integration with DNS Operations

These utility functions are used internally by pycares but can also be used directly when working with domain names and DNS data:

import pycares

def custom_dns_query(channel, raw_name, query_type, callback):
    """Example showing manual name processing."""
    try:
        # Process domain name using utility function
        encoded_name = pycares.parse_name(raw_name)
        
        # Use processed name in query
        # (Note: pycares.Channel.query() handles this internally)
        channel.query(encoded_name.decode('ascii'), query_type, callback)
        
    except (TypeError, RuntimeError, UnicodeDecodeError) as e:
        # Handle name processing errors
        callback(None, pycares.errno.ARES_EBADNAME)

# Usage
channel = pycares.Channel()
custom_dns_query(channel, "example.com", pycares.QUERY_TYPE_A, lambda r, e: print(r, e))

Module Exports

The utilities module exports the following functions in its __all__ list:

__all__ = ['ascii_bytes', 'maybe_str', 'parse_name']

These functions are also available directly from the main pycares module after import.

Install with Tessl CLI

npx tessl i tessl/pypi-pycares

docs

channel-management.md

dns-queries.md

error-handling.md

host-resolution.md

index.md

utilities.md

tile.json