Telethon/telethon_generator/parsers/errors.py
Lonami Exo 8224e5aabf Make use of pathlib nearly everywhere (breaks docs gen)
Python 3.6 introduced support for the os.PathLike interface,
which means Python 3.5 did not have it yet and attempting to
use it in os functions would fail. Instead we can use pathlib
for everything, but not all work is done yet.
2018-12-21 13:24:16 +01:00

71 lines
2.3 KiB
Python

import csv
import re
from ..utils import snake_to_camel_case
# Core base classes depending on the integer error code
KNOWN_BASE_CLASSES = {
303: 'InvalidDCError',
400: 'BadRequestError',
401: 'UnauthorizedError',
403: 'ForbiddenError',
404: 'NotFoundError',
406: 'AuthKeyError',
420: 'FloodError',
500: 'ServerError',
}
def _get_class_name(error_code):
"""
Gets the corresponding class name for the given error code,
this either being an integer (thus base error name) or str.
"""
if isinstance(error_code, int):
return KNOWN_BASE_CLASSES.get(
error_code, 'RPCError' + str(error_code).replace('-', 'Neg')
)
return snake_to_camel_case(
error_code.replace('FIRSTNAME', 'FIRST_NAME').lower(), suffix='Error')
class Error:
def __init__(self, codes, name, description):
# TODO Some errors have the same name but different integer codes
# Should these be split into different files or doesn't really matter?
# Telegram isn't exactly consistent with returned errors anyway.
self.int_code = codes[0]
self.str_code = name
self.subclass = _get_class_name(codes[0])
self.subclass_exists = codes[0] in KNOWN_BASE_CLASSES
self.description = description
self.has_captures = '_X' in name
if self.has_captures:
self.name = _get_class_name(name.replace('_X', ''))
self.pattern = name.replace('_X', r'_(\d+)')
self.capture_name = re.search(r'{(\w+)}', description).group(1)
else:
self.name = _get_class_name(name)
self.pattern = name
self.capture_name = None
def parse_errors(csv_file):
"""
Parses the input CSV file with columns (name, error codes, description)
and yields `Error` instances as a result.
"""
with csv_file.open(newline='') as f:
f = csv.reader(f)
next(f, None) # header
for line, (name, codes, description) in enumerate(f, start=2):
try:
codes = [int(x) for x in codes.split()] or [400]
except ValueError:
raise ValueError('Not all codes are integers '
'(line {})'.format(line)) from None
yield Error([int(x) for x in codes], name, description)