coding-client 1.21.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coding_client/__init__.py +1 -0
- coding_client/api/__init__.py +19 -0
- coding_client/api/exception_handlers.py +158 -0
- coding_client/api/logging_setup.py +44 -0
- coding_client/api/metrics.py +40 -0
- coding_client/api/openapi_config.py +124 -0
- coding_client/api/request_logging.py +60 -0
- coding_client/api/validation.py +150 -0
- coding_client/auth/__init__.py +78 -0
- coding_client/auth/_default_tenant.py +132 -0
- coding_client/auth/_header_trust.py +98 -0
- coding_client/auth/_onbehalf.py +315 -0
- coding_client/auth/_trusted_networks.py +94 -0
- coding_client/auth/dependencies.py +61 -0
- coding_client/auth/middleware.py +445 -0
- coding_client/auth/models.py +83 -0
- coding_client/auth/outbound.py +137 -0
- coding_client/auth/rbac.py +21 -0
- coding_client/auth/rbac_coding.py +5 -0
- coding_client/auth/tenant.py +650 -0
- coding_client/auth/websocket.py +148 -0
- coding_client/clients/__init__.py +24 -0
- coding_client/clients/base.py +131 -0
- coding_client/clients/coding_ai.py +33 -0
- coding_client/clients/coding_analysis.py +36 -0
- coding_client/clients/coding_containers.py +45 -0
- coding_client/clients/coding_github.py +127 -0
- coding_client/clients/coding_realtime.py +127 -0
- coding_client/clients/coding_security.py +51 -0
- coding_client/clients/coding_testing.py +31 -0
- coding_client/clients/coding_workspaces.py +265 -0
- coding_client/config/__init__.py +12 -0
- coding_client/config/base_settings.py +61 -0
- coding_client/config/yaml_config_loader.py +172 -0
- coding_client/db/__init__.py +42 -0
- coding_client/db/db_types.py +122 -0
- coding_client/db/exceptions.py +59 -0
- coding_client/db/postgres_connection.py +572 -0
- coding_client/db/tenant_query_helper.py +417 -0
- coding_client/db_init.py +49 -0
- coding_client/exceptions/__init__.py +67 -0
- coding_client/exceptions/api_exceptions.py +395 -0
- coding_client/exceptions/pydantic_ai_exceptions.py +533 -0
- coding_client/interfaces/__init__.py +22 -0
- coding_client/interfaces/cache_interface.py +179 -0
- coding_client/interfaces/container_interface.py +49 -0
- coding_client/interfaces/docker_interface.py +283 -0
- coding_client/interfaces/graph_interface.py +28 -0
- coding_client/interfaces/security_interface.py +72 -0
- coding_client/interfaces/webhook_interface.py +67 -0
- coding_client/llm/__init__.py +54 -0
- coding_client/llm/base_agent.py +195 -0
- coding_client/llm/context.py +121 -0
- coding_client/llm/responses.py +102 -0
- coding_client/llm/routing.py +82 -0
- coding_client/llm/settings.py +102 -0
- coding_client/models/__init__.py +62 -0
- coding_client/models/agent.py +38 -0
- coding_client/models/ai_test_failure.py +745 -0
- coding_client/models/analysis.py +330 -0
- coding_client/models/architecture.py +685 -0
- coding_client/models/bug.py +128 -0
- coding_client/models/code_graph.py +317 -0
- coding_client/models/container.py +241 -0
- coding_client/models/core.py +878 -0
- coding_client/models/docker_container.py +104 -0
- coding_client/models/github.py +293 -0
- coding_client/models/logging.py +29 -0
- coding_client/models/package_manager.py +257 -0
- coding_client/models/pr_validation.py +440 -0
- coding_client/models/pydantic_ai.py +395 -0
- coding_client/models/repo_scanner.py +249 -0
- coding_client/models/responses.py +431 -0
- coding_client/models/security.py +185 -0
- coding_client/models/static_analysis.py +508 -0
- coding_client/models/system.py +48 -0
- coding_client/models/test_executor.py +204 -0
- coding_client/models/testing.py +673 -0
- coding_client/models/testing_config.py +200 -0
- coding_client/models/validation.py +127 -0
- coding_client/models_init.py +272 -0
- coding_client/telemetry.py +195 -0
- coding_client/testing.py +180 -0
- coding_client/types/__init__.py +130 -0
- coding_client/types/constraint_types.py +276 -0
- coding_client/types/core_types.py +112 -0
- coding_client/types/state_machine.py +443 -0
- coding_client/utils/__init__.py +86 -0
- coding_client/utils/archive_utils.py +387 -0
- coding_client/utils/ast_debug.py +45 -0
- coding_client/utils/async_timeout.py +364 -0
- coding_client/utils/constants.py +518 -0
- coding_client/utils/content_processing.py +326 -0
- coding_client/utils/database.py +916 -0
- coding_client/utils/encoding_helper.py +222 -0
- coding_client/utils/enum_helpers.py +166 -0
- coding_client/utils/file_operations.py +177 -0
- coding_client/utils/filesystem_ops.py +528 -0
- coding_client/utils/http_client.py +562 -0
- coding_client/utils/path_utils.py +471 -0
- coding_client/utils/profiling.py +421 -0
- coding_client/utils/response_builder.py +240 -0
- coding_client/utils/retry_helper.py +712 -0
- coding_client/utils/security_validation.py +423 -0
- coding_client-1.21.2.dist-info/METADATA +234 -0
- coding_client-1.21.2.dist-info/RECORD +109 -0
- coding_client-1.21.2.dist-info/WHEEL +5 -0
- coding_client-1.21.2.dist-info/licenses/LICENSE +201 -0
- coding_client-1.21.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
"""File content processing utilities.
|
|
2
|
+
|
|
3
|
+
This module provides utilities for processing file content including
|
|
4
|
+
JSON/YAML operations, encoding detection, and format-specific handling.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import asyncio
|
|
10
|
+
import inspect
|
|
11
|
+
import json
|
|
12
|
+
import logging
|
|
13
|
+
from collections.abc import Callable
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any, TypeVar
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
import chardet
|
|
19
|
+
except ImportError:
|
|
20
|
+
chardet = None
|
|
21
|
+
import yaml
|
|
22
|
+
|
|
23
|
+
from .constants import DEFAULT_ENCODING
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
T = TypeVar("T")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ContentProcessingError(Exception):
|
|
31
|
+
"""Base exception for content processing operations."""
|
|
32
|
+
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class JSONProcessingError(ContentProcessingError):
|
|
37
|
+
"""Raised when JSON processing fails."""
|
|
38
|
+
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class YAMLProcessingError(ContentProcessingError):
|
|
43
|
+
"""Raised when YAML processing fails."""
|
|
44
|
+
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def detect_encoding(file_path: str | Path, sample_size: int = 10000) -> str:
|
|
49
|
+
"""Detect file encoding using chardet."""
|
|
50
|
+
path = Path(file_path)
|
|
51
|
+
|
|
52
|
+
if chardet is None:
|
|
53
|
+
# If chardet is not available, return default encoding
|
|
54
|
+
return DEFAULT_ENCODING
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
with open(path, "rb") as f:
|
|
58
|
+
sample = f.read(sample_size)
|
|
59
|
+
|
|
60
|
+
result = chardet.detect(sample)
|
|
61
|
+
encoding = result.get("encoding")
|
|
62
|
+
|
|
63
|
+
if encoding and result.get("confidence", 0) > 0.7:
|
|
64
|
+
return encoding
|
|
65
|
+
except Exception as e:
|
|
66
|
+
logger.warning(f"Error detecting encoding for {path}: {e}")
|
|
67
|
+
|
|
68
|
+
return DEFAULT_ENCODING
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
async def async_detect_encoding(file_path: str | Path, sample_size: int = 10000) -> str:
|
|
72
|
+
"""Asynchronously detect file encoding."""
|
|
73
|
+
return await asyncio.to_thread(detect_encoding, file_path, sample_size)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def read_json(
|
|
77
|
+
file_path: str | Path,
|
|
78
|
+
encoding: str = DEFAULT_ENCODING,
|
|
79
|
+
default: Any = None,
|
|
80
|
+
) -> Any:
|
|
81
|
+
"""Read JSON file with error handling."""
|
|
82
|
+
from .filesystem_ops import FileNotFoundError, read_file
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
content = read_file(file_path, encoding)
|
|
86
|
+
return json.loads(content)
|
|
87
|
+
except FileNotFoundError as e:
|
|
88
|
+
if default is not None:
|
|
89
|
+
logger.warning(f"JSON file not found {file_path}, using default: {e}")
|
|
90
|
+
return default
|
|
91
|
+
raise JSONProcessingError(f"JSON file not found: {file_path}") from e
|
|
92
|
+
except json.JSONDecodeError as e:
|
|
93
|
+
if default is not None:
|
|
94
|
+
logger.warning(f"Invalid JSON in {file_path}, using default: {e}")
|
|
95
|
+
return default
|
|
96
|
+
raise JSONProcessingError(f"Invalid JSON in {file_path}: {e}") from e
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
async def async_read_json(
|
|
100
|
+
file_path: str | Path,
|
|
101
|
+
encoding: str = DEFAULT_ENCODING,
|
|
102
|
+
default: Any = None,
|
|
103
|
+
) -> Any:
|
|
104
|
+
"""Asynchronously read JSON file with error handling."""
|
|
105
|
+
return await asyncio.to_thread(read_json, file_path, encoding, default)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def write_json(
|
|
109
|
+
file_path: str | Path,
|
|
110
|
+
data: Any,
|
|
111
|
+
encoding: str = DEFAULT_ENCODING,
|
|
112
|
+
indent: int = 2,
|
|
113
|
+
sort_keys: bool = True,
|
|
114
|
+
create_dirs: bool = True,
|
|
115
|
+
) -> Path:
|
|
116
|
+
"""Write data to JSON file."""
|
|
117
|
+
from .filesystem_ops import write_file
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
content = json.dumps(data, indent=indent, sort_keys=sort_keys, ensure_ascii=False)
|
|
121
|
+
return write_file(file_path, content, encoding, create_dirs)
|
|
122
|
+
except (TypeError, ValueError) as e:
|
|
123
|
+
raise JSONProcessingError(f"Failed to serialize data to JSON: {e}") from e
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
async def async_write_json(
|
|
127
|
+
file_path: str | Path,
|
|
128
|
+
data: Any,
|
|
129
|
+
encoding: str = DEFAULT_ENCODING,
|
|
130
|
+
indent: int = 2,
|
|
131
|
+
sort_keys: bool = True,
|
|
132
|
+
create_dirs: bool = True,
|
|
133
|
+
) -> Path:
|
|
134
|
+
"""Asynchronously write data to JSON file."""
|
|
135
|
+
return await asyncio.to_thread(
|
|
136
|
+
write_json, file_path, data, encoding, indent, sort_keys, create_dirs
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def read_yaml(
|
|
141
|
+
file_path: str | Path,
|
|
142
|
+
encoding: str = DEFAULT_ENCODING,
|
|
143
|
+
default: Any = None,
|
|
144
|
+
) -> Any:
|
|
145
|
+
"""Read YAML file with error handling."""
|
|
146
|
+
from .filesystem_ops import FileNotFoundError, read_file
|
|
147
|
+
|
|
148
|
+
try:
|
|
149
|
+
content = read_file(file_path, encoding)
|
|
150
|
+
return yaml.safe_load(content)
|
|
151
|
+
except FileNotFoundError as e:
|
|
152
|
+
if default is not None:
|
|
153
|
+
logger.warning(f"YAML file not found {file_path}, using default: {e}")
|
|
154
|
+
return default
|
|
155
|
+
raise YAMLProcessingError(f"YAML file not found: {file_path}") from e
|
|
156
|
+
except yaml.YAMLError as e:
|
|
157
|
+
if default is not None:
|
|
158
|
+
logger.warning(f"Invalid YAML in {file_path}, using default: {e}")
|
|
159
|
+
return default
|
|
160
|
+
raise YAMLProcessingError(f"Invalid YAML in {file_path}: {e}") from e
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
async def async_read_yaml(
|
|
164
|
+
file_path: str | Path,
|
|
165
|
+
encoding: str = DEFAULT_ENCODING,
|
|
166
|
+
default: Any = None,
|
|
167
|
+
) -> Any:
|
|
168
|
+
"""Asynchronously read YAML file with error handling."""
|
|
169
|
+
return await asyncio.to_thread(read_yaml, file_path, encoding, default)
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def write_yaml(
|
|
173
|
+
file_path: str | Path,
|
|
174
|
+
data: Any,
|
|
175
|
+
encoding: str = DEFAULT_ENCODING,
|
|
176
|
+
default_flow_style: bool = False,
|
|
177
|
+
create_dirs: bool = True,
|
|
178
|
+
) -> Path:
|
|
179
|
+
"""Write data to YAML file."""
|
|
180
|
+
from .filesystem_ops import write_file
|
|
181
|
+
|
|
182
|
+
try:
|
|
183
|
+
content = yaml.dump(data, default_flow_style=default_flow_style, allow_unicode=True)
|
|
184
|
+
return write_file(file_path, content, encoding, create_dirs)
|
|
185
|
+
except yaml.YAMLError as e:
|
|
186
|
+
raise YAMLProcessingError(f"Failed to serialize data to YAML: {e}") from e
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
async def async_write_yaml(
|
|
190
|
+
file_path: str | Path,
|
|
191
|
+
data: Any,
|
|
192
|
+
encoding: str = DEFAULT_ENCODING,
|
|
193
|
+
default_flow_style: bool = False,
|
|
194
|
+
create_dirs: bool = True,
|
|
195
|
+
) -> Path:
|
|
196
|
+
"""Asynchronously write data to YAML file."""
|
|
197
|
+
return await asyncio.to_thread(
|
|
198
|
+
write_yaml, file_path, data, encoding, default_flow_style, create_dirs
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def validate_json_content(content: str) -> bool:
|
|
203
|
+
"""Validate if string content is valid JSON."""
|
|
204
|
+
try:
|
|
205
|
+
json.loads(content)
|
|
206
|
+
return True
|
|
207
|
+
except (json.JSONDecodeError, TypeError):
|
|
208
|
+
return False
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def validate_yaml_content(content: str) -> bool:
|
|
212
|
+
"""Validate if string content is valid YAML."""
|
|
213
|
+
try:
|
|
214
|
+
yaml.safe_load(content)
|
|
215
|
+
return True
|
|
216
|
+
except yaml.YAMLError:
|
|
217
|
+
return False
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def format_json(
|
|
221
|
+
data: Any,
|
|
222
|
+
indent: int = 2,
|
|
223
|
+
sort_keys: bool = True,
|
|
224
|
+
ensure_ascii: bool = False,
|
|
225
|
+
) -> str:
|
|
226
|
+
"""Format data as JSON string."""
|
|
227
|
+
try:
|
|
228
|
+
return json.dumps(data, indent=indent, sort_keys=sort_keys, ensure_ascii=ensure_ascii)
|
|
229
|
+
except (TypeError, ValueError) as e:
|
|
230
|
+
raise JSONProcessingError(f"Failed to format as JSON: {e}") from e
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def format_yaml(
|
|
234
|
+
data: Any,
|
|
235
|
+
default_flow_style: bool = False,
|
|
236
|
+
allow_unicode: bool = True,
|
|
237
|
+
indent: int = 2,
|
|
238
|
+
) -> str:
|
|
239
|
+
"""Format data as YAML string."""
|
|
240
|
+
try:
|
|
241
|
+
return yaml.dump(
|
|
242
|
+
data,
|
|
243
|
+
default_flow_style=default_flow_style,
|
|
244
|
+
allow_unicode=allow_unicode,
|
|
245
|
+
indent=indent,
|
|
246
|
+
)
|
|
247
|
+
except yaml.YAMLError as e:
|
|
248
|
+
raise YAMLProcessingError(f"Failed to format as YAML: {e}") from e
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def process_files[T](
|
|
252
|
+
directory: str | Path,
|
|
253
|
+
processor: Callable[[Path], T],
|
|
254
|
+
pattern: str = "*",
|
|
255
|
+
recursive: bool = True,
|
|
256
|
+
parallel: bool = False,
|
|
257
|
+
max_workers: int = 4,
|
|
258
|
+
) -> list[T]:
|
|
259
|
+
"""Process multiple files with a callback function."""
|
|
260
|
+
from .path_utils import list_files
|
|
261
|
+
|
|
262
|
+
files = list_files(directory, pattern, recursive)
|
|
263
|
+
|
|
264
|
+
if not parallel:
|
|
265
|
+
return [processor(f) for f in files]
|
|
266
|
+
|
|
267
|
+
# Parallel processing
|
|
268
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
269
|
+
|
|
270
|
+
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
|
271
|
+
return list(executor.map(processor, files))
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
async def async_process_files[T](
|
|
275
|
+
directory: str | Path,
|
|
276
|
+
processor: Callable[[Path], T],
|
|
277
|
+
pattern: str = "*",
|
|
278
|
+
recursive: bool = True,
|
|
279
|
+
max_concurrent: int = 10,
|
|
280
|
+
) -> list[T]:
|
|
281
|
+
"""Asynchronously process multiple files."""
|
|
282
|
+
from .path_utils import list_files
|
|
283
|
+
|
|
284
|
+
files = await asyncio.to_thread(list_files, directory, pattern, recursive)
|
|
285
|
+
|
|
286
|
+
# Create semaphore for concurrency control
|
|
287
|
+
semaphore = asyncio.Semaphore(max_concurrent)
|
|
288
|
+
|
|
289
|
+
async def process_with_limit(file_path: Path) -> T:
|
|
290
|
+
async with semaphore:
|
|
291
|
+
if inspect.iscoroutinefunction(processor):
|
|
292
|
+
return await processor(file_path)
|
|
293
|
+
else:
|
|
294
|
+
return await asyncio.to_thread(processor, file_path)
|
|
295
|
+
|
|
296
|
+
tasks = [process_with_limit(f) for f in files]
|
|
297
|
+
return await asyncio.gather(*tasks)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
# Export all public functions
|
|
301
|
+
__all__ = [
|
|
302
|
+
# Exceptions
|
|
303
|
+
"ContentProcessingError",
|
|
304
|
+
"JSONProcessingError",
|
|
305
|
+
"YAMLProcessingError",
|
|
306
|
+
# Encoding
|
|
307
|
+
"detect_encoding",
|
|
308
|
+
"async_detect_encoding",
|
|
309
|
+
# JSON operations
|
|
310
|
+
"read_json",
|
|
311
|
+
"async_read_json",
|
|
312
|
+
"write_json",
|
|
313
|
+
"async_write_json",
|
|
314
|
+
"validate_json_content",
|
|
315
|
+
"format_json",
|
|
316
|
+
# YAML operations
|
|
317
|
+
"read_yaml",
|
|
318
|
+
"async_read_yaml",
|
|
319
|
+
"write_yaml",
|
|
320
|
+
"async_write_yaml",
|
|
321
|
+
"validate_yaml_content",
|
|
322
|
+
"format_yaml",
|
|
323
|
+
# Processing
|
|
324
|
+
"process_files",
|
|
325
|
+
"async_process_files",
|
|
326
|
+
]
|