lbry.error: save arguments on self and support for functions around arguments

This commit is contained in:
Lex Berezhny 2020-02-07 18:25:06 -05:00
parent ceb92838e7
commit db25f3282e
4 changed files with 59 additions and 8 deletions

View file

@ -53,7 +53,7 @@ Code | Name | Message
407 | DataDownload | Failed to download blob. *generic* 407 | DataDownload | Failed to download blob. *generic*
410 | Resolve | Failed to resolve '{url}'. 410 | Resolve | Failed to resolve '{url}'.
411 | ResolveTimeout | Failed to resolve '{url}' within the timeout. 411 | ResolveTimeout | Failed to resolve '{url}' within the timeout.
411 | ResolveCensored | Resolve of '{url}' was censored by channel with claim id '{censor_id}'. 411 | ResolveCensored | Resolve of '{url}' was censored by channel with claim id '{claim_id(censor_hash)}'.
420 | KeyFeeAboveMaxAllowed | {message} 420 | KeyFeeAboveMaxAllowed | {message}
421 | InvalidPassword | Password is invalid. 421 | InvalidPassword | Password is invalid.
422 | IncompatibleWalletServer | '{server}:{port}' has an incompatibly old version. 422 | IncompatibleWalletServer | '{server}:{port}' has an incompatibly old version.

View file

@ -1,4 +1,4 @@
from .base import BaseError from .base import BaseError, claim_id
class UserInputError(BaseError): class UserInputError(BaseError):
@ -16,18 +16,22 @@ class CommandError(UserInputError):
class CommandDoesNotExistError(CommandError): class CommandDoesNotExistError(CommandError):
def __init__(self, command): def __init__(self, command):
self.command = command
super().__init__(f"Command '{command}' does not exist.") super().__init__(f"Command '{command}' does not exist.")
class CommandDeprecatedError(CommandError): class CommandDeprecatedError(CommandError):
def __init__(self, command): def __init__(self, command):
self.command = command
super().__init__(f"Command '{command}' is deprecated.") super().__init__(f"Command '{command}' is deprecated.")
class CommandInvalidArgumentError(CommandError): class CommandInvalidArgumentError(CommandError):
def __init__(self, argument, command): def __init__(self, argument, command):
self.argument = argument
self.command = command
super().__init__(f"Invalid argument '{argument}' to command '{command}'.") super().__init__(f"Invalid argument '{argument}' to command '{command}'.")
@ -37,6 +41,7 @@ class CommandTemporarilyUnavailableError(CommandError):
""" """
def __init__(self, command): def __init__(self, command):
self.command = command
super().__init__(f"Command '{command}' is temporarily unavailable.") super().__init__(f"Command '{command}' is temporarily unavailable.")
@ -46,6 +51,7 @@ class CommandPermanentlyUnavailableError(CommandError):
""" """
def __init__(self, command): def __init__(self, command):
self.command = command
super().__init__(f"Command '{command}' is permanently unavailable.") super().__init__(f"Command '{command}' is permanently unavailable.")
@ -58,12 +64,15 @@ class InputValueError(UserInputError, ValueError):
class GenericInputValueError(InputValueError): class GenericInputValueError(InputValueError):
def __init__(self, value, argument): def __init__(self, value, argument):
self.value = value
self.argument = argument
super().__init__(f"The value '{value}' for argument '{argument}' is not valid.") super().__init__(f"The value '{value}' for argument '{argument}' is not valid.")
class InputValueIsNoneError(InputValueError): class InputValueIsNoneError(InputValueError):
def __init__(self, argument): def __init__(self, argument):
self.argument = argument
super().__init__(f"None or null is not valid value for argument '{argument}'.") super().__init__(f"None or null is not valid value for argument '{argument}'.")
@ -79,6 +88,7 @@ class ConfigWriteError(ConfigurationError):
""" """
def __init__(self, path): def __init__(self, path):
self.path = path
super().__init__(f"Cannot write configuration file '{path}'.") super().__init__(f"Cannot write configuration file '{path}'.")
@ -88,6 +98,7 @@ class ConfigReadError(ConfigurationError):
""" """
def __init__(self, path): def __init__(self, path):
self.path = path
super().__init__(f"Cannot find provided configuration file '{path}'.") super().__init__(f"Cannot find provided configuration file '{path}'.")
@ -97,18 +108,21 @@ class ConfigParseError(ConfigurationError):
""" """
def __init__(self, path): def __init__(self, path):
self.path = path
super().__init__(f"Failed to parse the configuration file '{path}'.") super().__init__(f"Failed to parse the configuration file '{path}'.")
class ConfigMissingError(ConfigurationError): class ConfigMissingError(ConfigurationError):
def __init__(self, path): def __init__(self, path):
self.path = path
super().__init__(f"Configuration file '{path}' is missing setting that has no default / fallback.") super().__init__(f"Configuration file '{path}' is missing setting that has no default / fallback.")
class ConfigInvalidError(ConfigurationError): class ConfigInvalidError(ConfigurationError):
def __init__(self, path): def __init__(self, path):
self.path = path
super().__init__(f"Configuration file '{path}' has setting with invalid value.") super().__init__(f"Configuration file '{path}' has setting with invalid value.")
@ -188,24 +202,29 @@ class DataDownloadError(WalletError):
class ResolveError(WalletError): class ResolveError(WalletError):
def __init__(self, url): def __init__(self, url):
self.url = url
super().__init__(f"Failed to resolve '{url}'.") super().__init__(f"Failed to resolve '{url}'.")
class ResolveTimeoutError(WalletError): class ResolveTimeoutError(WalletError):
def __init__(self, url): def __init__(self, url):
self.url = url
super().__init__(f"Failed to resolve '{url}' within the timeout.") super().__init__(f"Failed to resolve '{url}' within the timeout.")
class ResolveCensoredError(WalletError): class ResolveCensoredError(WalletError):
def __init__(self, url, censor_id): def __init__(self, url, censor_hash):
super().__init__(f"Resolve of '{url}' was censored by channel with claim id '{censor_id}'.") self.url = url
self.censor_hash = censor_hash
super().__init__(f"Resolve of '{url}' was censored by channel with claim id '{claim_id(censor_hash)}'.")
class KeyFeeAboveMaxAllowedError(WalletError): class KeyFeeAboveMaxAllowedError(WalletError):
def __init__(self, message): def __init__(self, message):
self.message = message
super().__init__(f"{message}") super().__init__(f"{message}")
@ -218,6 +237,8 @@ class InvalidPasswordError(WalletError):
class IncompatibleWalletServerError(WalletError): class IncompatibleWalletServerError(WalletError):
def __init__(self, server, port): def __init__(self, server, port):
self.server = server
self.port = port
super().__init__(f"'{server}:{port}' has an incompatibly old version.") super().__init__(f"'{server}:{port}' has an incompatibly old version.")
@ -278,30 +299,35 @@ class DownloadCancelledError(BlobError):
class DownloadSDTimeoutError(BlobError): class DownloadSDTimeoutError(BlobError):
def __init__(self, download): def __init__(self, download):
self.download = download
super().__init__(f"Failed to download sd blob {download} within timeout.") super().__init__(f"Failed to download sd blob {download} within timeout.")
class DownloadDataTimeoutError(BlobError): class DownloadDataTimeoutError(BlobError):
def __init__(self, download): def __init__(self, download):
self.download = download
super().__init__(f"Failed to download data blobs for sd hash {download} within timeout.") super().__init__(f"Failed to download data blobs for sd hash {download} within timeout.")
class InvalidStreamDescriptorError(BlobError): class InvalidStreamDescriptorError(BlobError):
def __init__(self, message): def __init__(self, message):
self.message = message
super().__init__(f"{message}") super().__init__(f"{message}")
class InvalidDataError(BlobError): class InvalidDataError(BlobError):
def __init__(self, message): def __init__(self, message):
self.message = message
super().__init__(f"{message}") super().__init__(f"{message}")
class InvalidBlobHashError(BlobError): class InvalidBlobHashError(BlobError):
def __init__(self, message): def __init__(self, message):
self.message = message
super().__init__(f"{message}") super().__init__(f"{message}")
@ -314,12 +340,14 @@ class ComponentError(BaseError):
class ComponentStartConditionNotMetError(ComponentError): class ComponentStartConditionNotMetError(ComponentError):
def __init__(self, components): def __init__(self, components):
self.components = components
super().__init__(f"Unresolved dependencies for: {components}") super().__init__(f"Unresolved dependencies for: {components}")
class ComponentsNotStartedError(ComponentError): class ComponentsNotStartedError(ComponentError):
def __init__(self, message): def __init__(self, message):
self.message = message
super().__init__(f"{message}") super().__init__(f"{message}")
@ -332,16 +360,20 @@ class CurrencyExchangeError(BaseError):
class InvalidExchangeRateResponseError(CurrencyExchangeError): class InvalidExchangeRateResponseError(CurrencyExchangeError):
def __init__(self, source, reason): def __init__(self, source, reason):
self.source = source
self.reason = reason
super().__init__(f"Failed to get exchange rate from {source}: {reason}") super().__init__(f"Failed to get exchange rate from {source}: {reason}")
class CurrencyConversionError(CurrencyExchangeError): class CurrencyConversionError(CurrencyExchangeError):
def __init__(self, message): def __init__(self, message):
self.message = message
super().__init__(f"{message}") super().__init__(f"{message}")
class InvalidCurrencyError(CurrencyExchangeError): class InvalidCurrencyError(CurrencyExchangeError):
def __init__(self, currency): def __init__(self, currency):
self.currency = currency
super().__init__(f"Invalid currency: {currency} is not a supported currency.") super().__init__(f"Invalid currency: {currency} is not a supported currency.")

View file

@ -1,2 +1,9 @@
from binascii import hexlify
def claim_id(claim_hash):
return hexlify(claim_hash[::-1]).decode()
class BaseError(Exception): class BaseError(Exception):
pass pass

View file

@ -13,10 +13,12 @@ class {name}({parents}):{doc}
""" """
INIT = """ INIT = """
def __init__({args}): def __init__({args}):{fields}
super().__init__({format}"{message}") super().__init__({format}"{message}")
""" """
FUNCTIONS = ['claim_id']
class ErrorClass: class ErrorClass:
@ -50,10 +52,19 @@ class ErrorClass:
def get_arguments(self): def get_arguments(self):
args = ['self'] args = ['self']
for arg in re.findall('{([a-z0-1_]+)}', self.message): for arg in re.findall('{([a-z0-1_\(\)]+)}', self.message):
for func in FUNCTIONS:
if arg.startswith(f'{func}('):
arg = arg[len(f'{func}('):-1]
break
args.append(arg) args.append(arg)
return args return args
def get_fields(self, args):
if len(args) > 1:
return f''.join(f'\n{INDENT*2}self.{field} = {field}' for field in args[1:])
return ''
@staticmethod @staticmethod
def get_doc_string(doc): def get_doc_string(doc):
if doc: if doc:
@ -69,7 +80,8 @@ class ErrorClass:
args = self.get_arguments() args = self.get_arguments()
if self.is_leaf: if self.is_leaf:
out.write((CLASS + INIT).format( out.write((CLASS + INIT).format(
name=self.class_name, parents=', '.join(parents), args=', '.join(args), name=self.class_name, parents=', '.join(parents),
args=', '.join(args), fields=self.get_fields(args),
message=self.message, doc=self.get_doc_string(self.comment), format='f' if len(args) > 1 else '' message=self.message, doc=self.get_doc_string(self.comment), format='f' if len(args) > 1 else ''
)) ))
else: else:
@ -102,7 +114,7 @@ def find_parent(stack, child):
def generate(out): def generate(out):
out.write('from .base import BaseError\n') out.write(f"from .base import BaseError, {', '.join(FUNCTIONS)}\n")
stack = {} stack = {}
for error in get_errors(): for error in get_errors():
error.render(out, find_parent(stack, error)) error.render(out, find_parent(stack, error))