codekingpro/portable-devtools
115k
1from typing import Union, Optional2 3"""4_utils.py5websocket - WebSocket client library for Python6 7Copyright 2025 engn33r8 9Licensed under the Apache License, Version 2.0 (the "License");10you may not use this file except in compliance with the License.11You may obtain a copy of the License at12 13 http://www.apache.org/licenses/LICENSE-2.014 15Unless required by applicable law or agreed to in writing, software16distributed under the License is distributed on an "AS IS" BASIS,17WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.18See the License for the specific language governing permissions and19limitations under the License.20"""21__all__ = ["NoLock", "validate_utf8", "extract_err_message", "extract_error_code"]22 23 24class NoLock:25 def __enter__(self) -> None:26 pass27 28 def __exit__(self, exc_type, exc_value, traceback) -> None:29 pass30 31 32try:33 # If wsaccel is available we use compiled routines to validate UTF-834 # strings.35 from wsaccel.utf8validator import Utf8Validator36 37 def _validate_utf8(utfbytes: Union[str, bytes]) -> bool:38 result: bool = Utf8Validator().validate(utfbytes)[0]39 return result40 41except ImportError:42 # UTF-8 validator43 # python implementation of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/44 45 _UTF8_ACCEPT = 046 _UTF8_REJECT = 1247 48 _UTF8D = [49 # The first part of the table maps bytes to character classes that50 # to reduce the size of the transition table and create bitmasks.51 0,52 0,53 0,54 0,55 0,56 0,57 0,58 0,59 0,60 0,61 0,62 0,63 0,64 0,65 0,66 0,67 0,68 0,69 0,70 0,71 0,72 0,73 0,74 0,75 0,76 0,77 0,78 0,79 0,80 0,81 0,82 0,83 0,84 0,85 0,86 0,87 0,88 0,89 0,90 0,91 0,92 0,93 0,94 0,95 0,96 0,97 0,98 0,99 0,100 0,101 0,102 0,103 0,104 0,105 0,106 0,107 0,108 0,109 0,110 0,111 0,112 0,113 0,114 0,115 0,116 0,117 0,118 0,119 0,120 0,121 0,122 0,123 0,124 0,125 0,126 0,127 0,128 0,129 0,130 0,131 0,132 0,133 0,134 0,135 0,136 0,137 0,138 0,139 0,140 0,141 0,142 0,143 0,144 0,145 0,146 0,147 0,148 0,149 0,150 0,151 0,152 0,153 0,154 0,155 0,156 0,157 0,158 0,159 0,160 0,161 0,162 0,163 0,164 0,165 0,166 0,167 0,168 0,169 0,170 0,171 0,172 0,173 0,174 0,175 0,176 0,177 0,178 0,179 1,180 1,181 1,182 1,183 1,184 1,185 1,186 1,187 1,188 1,189 1,190 1,191 1,192 1,193 1,194 1,195 9,196 9,197 9,198 9,199 9,200 9,201 9,202 9,203 9,204 9,205 9,206 9,207 9,208 9,209 9,210 9,211 7,212 7,213 7,214 7,215 7,216 7,217 7,218 7,219 7,220 7,221 7,222 7,223 7,224 7,225 7,226 7,227 7,228 7,229 7,230 7,231 7,232 7,233 7,234 7,235 7,236 7,237 7,238 7,239 7,240 7,241 7,242 7,243 8,244 8,245 2,246 2,247 2,248 2,249 2,250 2,251 2,252 2,253 2,254 2,255 2,256 2,257 2,258 2,259 2,260 2,261 2,262 2,263 2,264 2,265 2,266 2,267 2,268 2,269 2,270 2,271 2,272 2,273 2,274 2,275 10,276 3,277 3,278 3,279 3,280 3,281 3,282 3,283 3,284 3,285 3,286 3,287 3,288 4,289 3,290 3,291 11,292 6,293 6,294 6,295 5,296 8,297 8,298 8,299 8,300 8,301 8,302 8,303 8,304 8,305 8,306 8,307 # The second part is a transition table that maps a combination308 # of a state of the automaton and a character class to a state.309 0,310 12,311 24,312 36,313 60,314 96,315 84,316 12,317 12,318 12,319 48,320 72,321 12,322 12,323 12,324 12,325 12,326 12,327 12,328 12,329 12,330 12,331 12,332 12,333 12,334 0,335 12,336 12,337 12,338 12,339 12,340 0,341 12,342 0,343 12,344 12,345 12,346 24,347 12,348 12,349 12,350 12,351 12,352 24,353 12,354 24,355 12,356 12,357 12,358 12,359 12,360 12,361 12,362 12,363 12,364 24,365 12,366 12,367 12,368 12,369 12,370 24,371 12,372 12,373 12,374 12,375 12,376 12,377 12,378 24,379 12,380 12,381 12,382 12,383 12,384 12,385 12,386 12,387 12,388 36,389 12,390 36,391 12,392 12,393 12,394 36,395 12,396 12,397 12,398 12,399 12,400 36,401 12,402 36,403 12,404 12,405 12,406 36,407 12,408 12,409 12,410 12,411 12,412 12,413 12,414 12,415 12,416 12,417 ]418 419 def _decode(state: int, codep: int, ch: int) -> tuple:420 tp = _UTF8D[ch]421 422 codep = (423 (ch & 0x3F) | (codep << 6) if (state != _UTF8_ACCEPT) else (0xFF >> tp) & ch424 )425 state = _UTF8D[256 + state + tp]426 427 return state, codep428 429 def _validate_utf8(utfbytes: Union[str, bytes]) -> bool:430 state = _UTF8_ACCEPT431 codep = 0432 for i in utfbytes:433 state, codep = _decode(state, codep, int(i))434 if state == _UTF8_REJECT:435 return False436 437 return True438 439 440def validate_utf8(utfbytes: Union[str, bytes]) -> bool:441 """442 validate utf8 byte string.443 utfbytes: utf byte string to check.444 return value: if valid utf8 string, return true. Otherwise, return false.445 """446 return _validate_utf8(utfbytes)447 448 449def extract_err_message(exception: Exception) -> Optional[str]:450 if exception.args:451 exception_message: str = exception.args[0]452 return exception_message453 else:454 return None455 456 457def extract_error_code(exception: Exception) -> Optional[int]:458 if exception.args and len(exception.args) > 1:459 return exception.args[0] if isinstance(exception.args[0], int) else None460 return None461 