0
# Utility Functions
1
2
String encoding and domain name processing utilities for handling international domain names, proper ASCII encoding, and data conversion within pycares operations.
3
4
## Capabilities
5
6
### String Encoding
7
8
Convert various string and bytes types to appropriate formats for DNS operations.
9
10
```python { .api }
11
def ascii_bytes(data):
12
"""
13
Convert string or bytes data to ASCII bytes.
14
15
Args:
16
data: Union[str, bytes] - Input data to convert
17
18
Returns:
19
bytes: ASCII-encoded bytes
20
21
Raises:
22
TypeError: If data is neither str nor bytes
23
"""
24
25
def maybe_str(data):
26
"""
27
Convert bytes to string if possible, otherwise return as-is.
28
29
Attempts to decode bytes data to ASCII string. If decoding fails,
30
returns the original bytes object.
31
32
Args:
33
data: Union[str, bytes] - Input data to convert
34
35
Returns:
36
Union[str, bytes]: String if decodable to ASCII, otherwise bytes
37
38
Raises:
39
TypeError: If data is neither str nor bytes
40
"""
41
```
42
43
**Usage Example:**
44
45
```python
46
import pycares
47
48
# Convert string to ASCII bytes
49
hostname_bytes = pycares.ascii_bytes("example.com")
50
print(hostname_bytes) # b'example.com'
51
52
# Convert bytes to string if possible
53
result = pycares.maybe_str(b"example.com")
54
print(result) # 'example.com'
55
56
# Binary data stays as bytes
57
binary_data = b'\x00\x01\x02'
58
result = pycares.maybe_str(binary_data)
59
print(type(result)) # <class 'bytes'>
60
```
61
62
### Domain Name Processing
63
64
Process domain names for DNS queries, including support for internationalized domain names (IDNA).
65
66
```python { .api }
67
def parse_name(name):
68
"""
69
Parse and encode domain name for DNS queries.
70
71
Handles both ASCII and internationalized domain names. For ASCII names,
72
performs direct encoding. For international domain names, uses IDNA 2008
73
encoding if the idna package is available, otherwise falls back to
74
built-in IDNA 2003 encoding.
75
76
Args:
77
name: Union[str, bytes] - Domain name to parse
78
79
Returns:
80
bytes: Properly encoded domain name for DNS queries
81
82
Raises:
83
TypeError: If name is neither str nor bytes
84
RuntimeError: If domain part exceeds 253 characters
85
"""
86
```
87
88
**Usage Example:**
89
90
```python
91
import pycares
92
93
# ASCII domain name
94
ascii_domain = pycares.parse_name("example.com")
95
print(ascii_domain) # b'example.com'
96
97
# International domain name (requires idna package for IDNA 2008)
98
try:
99
intl_domain = pycares.parse_name("例え.テスト")
100
print(intl_domain) # Encoded bytes representation
101
except RuntimeError as e:
102
print(f"Domain name too long: {e}")
103
104
# Bytes input passes through
105
bytes_domain = pycares.parse_name(b"example.org")
106
print(bytes_domain) # b'example.org'
107
```
108
109
## IDNA Support
110
111
pycares provides enhanced internationalized domain name support when the optional `idna` package is installed:
112
113
```python
114
# Install with IDNA 2008 support
115
# pip install pycares[idna]
116
```
117
118
### IDNA 2008 vs IDNA 2003
119
120
- **With idna package**: Uses modern IDNA 2008 standard for better Unicode support
121
- **Without idna package**: Falls back to Python's built-in IDNA 2003 codec
122
- **ASCII domains**: No difference, processed efficiently in both cases
123
124
### Domain Length Limits
125
126
The `parse_name` function enforces DNS domain length limits:
127
128
- Individual labels (parts between dots) must be ≤ 253 characters after encoding
129
- Total domain name length should comply with DNS standards
130
131
**Example with Error Handling:**
132
133
```python
134
import pycares
135
136
def safe_parse_name(domain):
137
"""Safely parse domain name with error handling."""
138
try:
139
return pycares.parse_name(domain)
140
except TypeError:
141
print(f"Invalid domain type: {type(domain)}")
142
return None
143
except RuntimeError as e:
144
print(f"Domain name error: {e}")
145
return None
146
147
# Test with various inputs
148
domains = [
149
"example.com", # ASCII domain
150
"例え.テスト", # International domain
151
b"binary.domain", # Bytes input
152
123, # Invalid type
153
"a" * 300 + ".com" # Too long
154
]
155
156
for domain in domains:
157
result = safe_parse_name(domain)
158
if result:
159
print(f"Parsed: {domain} -> {result}")
160
else:
161
print(f"Failed to parse: {domain}")
162
```
163
164
## Integration with DNS Operations
165
166
These utility functions are used internally by pycares but can also be used directly when working with domain names and DNS data:
167
168
```python
169
import pycares
170
171
def custom_dns_query(channel, raw_name, query_type, callback):
172
"""Example showing manual name processing."""
173
try:
174
# Process domain name using utility function
175
encoded_name = pycares.parse_name(raw_name)
176
177
# Use processed name in query
178
# (Note: pycares.Channel.query() handles this internally)
179
channel.query(encoded_name.decode('ascii'), query_type, callback)
180
181
except (TypeError, RuntimeError, UnicodeDecodeError) as e:
182
# Handle name processing errors
183
callback(None, pycares.errno.ARES_EBADNAME)
184
185
# Usage
186
channel = pycares.Channel()
187
custom_dns_query(channel, "example.com", pycares.QUERY_TYPE_A, lambda r, e: print(r, e))
188
```
189
190
## Module Exports
191
192
The utilities module exports the following functions in its `__all__` list:
193
194
```python { .api }
195
__all__ = ['ascii_bytes', 'maybe_str', 'parse_name']
196
```
197
198
These functions are also available directly from the main pycares module after import.