mirror of
https://github.com/hypervortex/VH-Bombsquad-Modded-Server-Files
synced 2025-11-07 17:36:08 +00:00
Added new files
This commit is contained in:
parent
5e004af549
commit
77ccb73089
1783 changed files with 566966 additions and 0 deletions
244
dist/ba_data/python/efro/error.py
vendored
Normal file
244
dist/ba_data/python/efro/error.py
vendored
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
# Released under the MIT License. See LICENSE for details.
|
||||
#
|
||||
"""Common errors and related functionality."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
import errno
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
|
||||
|
||||
class CleanError(Exception):
|
||||
"""An error that can be presented to the user as a simple message.
|
||||
|
||||
These errors should be completely self-explanatory, to the point where
|
||||
a traceback or other context would not be useful.
|
||||
|
||||
A CleanError with no message can be used to inform a script to fail
|
||||
without printing any message.
|
||||
|
||||
This should generally be limited to errors that will *always* be
|
||||
presented to the user (such as those in high level tool code).
|
||||
Exceptions that may be caught and handled by other code should use
|
||||
more descriptive exception types.
|
||||
"""
|
||||
|
||||
def pretty_print(self, flush: bool = False) -> None:
|
||||
"""Print the error to stdout, using red colored output if available.
|
||||
|
||||
If the error has an empty message, prints nothing (not even a newline).
|
||||
"""
|
||||
from efro.terminal import Clr
|
||||
|
||||
errstr = str(self)
|
||||
if errstr:
|
||||
print(f'{Clr.SRED}{errstr}{Clr.RST}', flush=flush)
|
||||
|
||||
|
||||
class CommunicationError(Exception):
|
||||
"""A communication related error has occurred.
|
||||
|
||||
This covers anything network-related going wrong in the sending
|
||||
of data or receiving of a response. Basically anything that is out
|
||||
of our control should get lumped in here. This error does not imply
|
||||
that data was not received on the other end; only that a full
|
||||
acknowledgement round trip was not completed.
|
||||
|
||||
These errors should be gracefully handled whenever possible, as
|
||||
occasional network issues are unavoidable.
|
||||
"""
|
||||
|
||||
|
||||
class RemoteError(Exception):
|
||||
"""An error occurred on the other end of some connection.
|
||||
|
||||
This occurs when communication succeeds but another type of error
|
||||
occurs remotely. The error string can consist of a remote stack
|
||||
trace or a simple message depending on the context.
|
||||
|
||||
Communication systems should raise more specific error types locally
|
||||
when more introspection/control is needed; this is intended somewhat
|
||||
as a catch-all.
|
||||
"""
|
||||
|
||||
def __init__(self, msg: str, peer_desc: str):
|
||||
super().__init__(msg)
|
||||
self._peer_desc = peer_desc
|
||||
|
||||
def __str__(self) -> str:
|
||||
s = ''.join(str(arg) for arg in self.args)
|
||||
# Indent so we can more easily tell what is the remote part when
|
||||
# this is in the middle of a long exception chain.
|
||||
padding = ' '
|
||||
s = ''.join(padding + line for line in s.splitlines(keepends=True))
|
||||
return f'The following occurred on {self._peer_desc}:\n{s}'
|
||||
|
||||
|
||||
class IntegrityError(ValueError):
|
||||
"""Data has been tampered with or corrupted in some form."""
|
||||
|
||||
|
||||
class AuthenticationError(Exception):
|
||||
"""Authentication has failed for some operation.
|
||||
|
||||
This can be raised if server-side-verification does not match
|
||||
client-supplied credentials, if an invalid password is supplied
|
||||
for a sign-in attempt, etc.
|
||||
"""
|
||||
|
||||
|
||||
def is_urllib_communication_error(exc: BaseException, url: str | None) -> bool:
|
||||
"""Is the provided exception from urllib a communication-related error?
|
||||
|
||||
Url, if provided can provide extra context for when to treat an error
|
||||
as such an error.
|
||||
|
||||
This should be passed an exception which resulted from opening or
|
||||
reading a urllib Request. It returns True for any errors that could
|
||||
conceivably arise due to unavailable/poor network connections,
|
||||
firewall/connectivity issues, or other issues out of our control.
|
||||
These errors can often be safely ignored or presented to the user
|
||||
as general 'network-unavailable' states.
|
||||
"""
|
||||
import urllib.error
|
||||
import http.client
|
||||
import socket
|
||||
|
||||
if isinstance(
|
||||
exc,
|
||||
(
|
||||
urllib.error.URLError,
|
||||
ConnectionError,
|
||||
http.client.IncompleteRead,
|
||||
http.client.BadStatusLine,
|
||||
http.client.RemoteDisconnected,
|
||||
socket.timeout,
|
||||
),
|
||||
):
|
||||
|
||||
# Special case: although an HTTPError is a subclass of URLError,
|
||||
# we don't consider it a communication error. It generally means we
|
||||
# have successfully communicated with the server but what we are asking
|
||||
# for is not there/etc.
|
||||
if isinstance(exc, urllib.error.HTTPError):
|
||||
|
||||
# Special sub-case: appspot.com hosting seems to give 403 errors
|
||||
# (forbidden) to some countries. I'm assuming for legal reasons?..
|
||||
# Let's consider that a communication error since its out of our
|
||||
# control so we don't fill up logs with it.
|
||||
if exc.code == 403 and url is not None and '.appspot.com' in url:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
if isinstance(exc, OSError):
|
||||
if exc.errno == 10051: # Windows unreachable network error.
|
||||
return True
|
||||
if exc.errno in {
|
||||
errno.ETIMEDOUT,
|
||||
errno.EHOSTUNREACH,
|
||||
errno.ENETUNREACH,
|
||||
}:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def is_requests_communication_error(exc: BaseException) -> bool:
|
||||
"""Is the provided exception a communication-related error from requests?"""
|
||||
import requests
|
||||
|
||||
# Looks like this maps pretty well onto requests' ConnectionError
|
||||
return isinstance(exc, requests.ConnectionError)
|
||||
|
||||
|
||||
def is_udp_communication_error(exc: BaseException) -> bool:
|
||||
"""Should this udp-related exception be considered a communication error?
|
||||
|
||||
This should be passed an exception which resulted from creating and
|
||||
using a socket.SOCK_DGRAM type socket. It should return True for any
|
||||
errors that could conceivably arise due to unavailable/poor network
|
||||
conditions, firewall/connectivity issues, etc. These issues can often
|
||||
be safely ignored or presented to the user as general
|
||||
'network-unavailable' states.
|
||||
"""
|
||||
if isinstance(exc, ConnectionRefusedError | TimeoutError):
|
||||
return True
|
||||
if isinstance(exc, OSError):
|
||||
if exc.errno == 10051: # Windows unreachable network error.
|
||||
return True
|
||||
if exc.errno in {
|
||||
errno.EADDRNOTAVAIL,
|
||||
errno.ETIMEDOUT,
|
||||
errno.EHOSTUNREACH,
|
||||
errno.ENETUNREACH,
|
||||
errno.EINVAL,
|
||||
errno.EPERM,
|
||||
errno.EACCES,
|
||||
# Windows 'invalid argument' error.
|
||||
10022,
|
||||
# Windows 'a socket operation was attempted to'
|
||||
# 'an unreachable network' error.
|
||||
10051,
|
||||
}:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def is_asyncio_streams_communication_error(exc: BaseException) -> bool:
|
||||
"""Should this streams error be considered a communication error?
|
||||
|
||||
This should be passed an exception which resulted from creating and
|
||||
using asyncio streams. It should return True for any errors that could
|
||||
conceivably arise due to unavailable/poor network connections,
|
||||
firewall/connectivity issues, etc. These issues can often be safely
|
||||
ignored or presented to the user as general 'connection-lost' events.
|
||||
"""
|
||||
# pylint: disable=too-many-return-statements
|
||||
import ssl
|
||||
|
||||
if isinstance(
|
||||
exc,
|
||||
(
|
||||
ConnectionError,
|
||||
TimeoutError,
|
||||
EOFError,
|
||||
),
|
||||
):
|
||||
return True
|
||||
|
||||
# Also some specific errno ones.
|
||||
if isinstance(exc, OSError):
|
||||
if exc.errno == 10051: # Windows unreachable network error.
|
||||
return True
|
||||
if exc.errno in {
|
||||
errno.ETIMEDOUT,
|
||||
errno.EHOSTUNREACH,
|
||||
errno.ENETUNREACH,
|
||||
}:
|
||||
return True
|
||||
|
||||
# Am occasionally getting a specific SSL error on shutdown which I
|
||||
# believe is harmless (APPLICATION_DATA_AFTER_CLOSE_NOTIFY).
|
||||
# It sounds like it may soon be ignored by Python (as of March 2022).
|
||||
# Let's still complain, however, if we get any SSL errors besides
|
||||
# this one. https://bugs.python.org/issue39951
|
||||
if isinstance(exc, ssl.SSLError):
|
||||
excstr = str(exc)
|
||||
if 'APPLICATION_DATA_AFTER_CLOSE_NOTIFY' in excstr:
|
||||
return True
|
||||
|
||||
# Also occasionally am getting WRONG_VERSION_NUMBER ssl errors;
|
||||
# Assuming this just means client is attempting to connect from some
|
||||
# outdated browser or whatnot.
|
||||
if 'SSL: WRONG_VERSION_NUMBER' in excstr:
|
||||
return True
|
||||
|
||||
# And seeing this very rarely; assuming its just data corruption?
|
||||
if 'SSL: DECRYPTION_FAILED_OR_BAD_RECORD_MAC' in excstr:
|
||||
return True
|
||||
|
||||
return False
|
||||
Loading…
Add table
Add a link
Reference in a new issue