From 200d3c0360e18ad032c060b0f13e1c38b2959b01 Mon Sep 17 00:00:00 2001 From: Lonami Exo Date: Sat, 14 Apr 2018 17:22:39 +0200 Subject: [PATCH] Clean-up unused methods and reuse more common utils --- telethon/errors/__init__.py | 1 + telethon_generator/parsers/errors.py | 12 +++---- telethon_generator/parsers/tlobject.py | 43 +++++--------------------- telethon_generator/tl_generator.py | 19 ++++++------ telethon_generator/utils.py | 8 +++++ 5 files changed, 30 insertions(+), 53 deletions(-) create mode 100644 telethon_generator/utils.py diff --git a/telethon/errors/__init__.py b/telethon/errors/__init__.py index d9875849..8b4e9f88 100644 --- a/telethon/errors/__init__.py +++ b/telethon/errors/__init__.py @@ -12,6 +12,7 @@ from .common import ( ) # This imports the base errors too, as they're imported there +from .rpc_base_errors import * from .rpc_error_list import * diff --git a/telethon_generator/parsers/errors.py b/telethon_generator/parsers/errors.py index 1b0e1552..869ca96e 100644 --- a/telethon_generator/parsers/errors.py +++ b/telethon_generator/parsers/errors.py @@ -1,7 +1,8 @@ import json +import re from collections import defaultdict -import re +from ..utils import snake_to_camel_case # Core base classes depending on the integer error code KNOWN_BASE_CLASSES = { @@ -45,13 +46,8 @@ def _get_class_name(error_code): error_code, 'RPCError' + str(error_code).replace('-', 'Neg') ) - if 'FIRSTNAME' in error_code: - error_code = error_code.replace('FIRSTNAME', 'FIRST_NAME') - - result = re.sub( - r'_([a-z])', lambda m: m.group(1).upper(), error_code.lower() - ) - return result[:1].upper() + result[1:].replace('_', '') + 'Error' + return snake_to_camel_case(error_code.replace('FIRSTNAME', 'FIRST_NAME'), + suffix='Error') class Error: diff --git a/telethon_generator/parsers/tlobject.py b/telethon_generator/parsers/tlobject.py index b562e0b7..668bd5e2 100644 --- a/telethon_generator/parsers/tlobject.py +++ b/telethon_generator/parsers/tlobject.py @@ -1,6 +1,8 @@ import re from zlib import crc32 +from ..utils import snake_to_camel_case + CORE_TYPES = ( 0xbc799737, # boolFalse#bc799737 = Bool; 0x997275b5, # boolTrue#997275b5 = Bool; @@ -31,6 +33,7 @@ class TLObject: self.args = args self.result = result self.is_function = is_function + self.id = None if object_id is None: self.id = self.infer_id() else: @@ -38,20 +41,8 @@ class TLObject: assert self.id == self.infer_id(),\ 'Invalid inferred ID for ' + repr(self) - def class_name(self): - """Gets the class name following the Python style guidelines""" - return self.class_name_for(self.name, self.is_function) - - @staticmethod - def class_name_for(typename, is_function=False): - """Gets the class name following the Python style guidelines""" - # Courtesy of http://stackoverflow.com/a/31531797/4759433 - result = re.sub(r'_([a-z])', lambda m: m.group(1).upper(), typename) - result = result[:1].upper() + result[1:].replace('_', '') - # If it's a function, let it end with "Request" to identify them - if is_function: - result += 'Request' - return result + self.class_name = snake_to_camel_case( + self.name, suffix='Request' if self.is_function else '') def sorted_args(self): """Returns the arguments properly sorted and ready to plug-in @@ -62,11 +53,10 @@ class TLObject: key=lambda x: x.is_flag or x.can_be_inferred) def __repr__(self, ignore_id=False): - if getattr(self, 'id', None) is None or ignore_id: + if self.id is None or ignore_id: hex_id = '' else: - # Skip 0x and add 0's for padding - hex_id = '#' + hex(self.id)[2:].rjust(8, '0') + hex_id = '#{:08x}'.format(self.id) if self.args: args = ' ' + ' '.join([repr(arg) for arg in self.args]) @@ -90,25 +80,6 @@ class TLObject: ) return crc32(representation.encode('ascii')) - def __str__(self): - # Some arguments are not valid for being represented, - # such as the flag indicator or generic definition - # (these have no explicit values until used) - valid_args = [arg for arg in self.args - if not arg.flag_indicator and not arg.generic_definition] - - args = ', '.join(['{}={{}}'.format(arg.name) for arg in valid_args]) - - # Since Python's default representation for lists is using repr(), - # we need to str() manually on every item - args_format = ', '.join( - ['str(self.{})'.format(arg.name) if not arg.is_vector else - 'None if not self.{0} else [str(_) for _ in self.{0}]'.format( - arg.name) for arg in valid_args]) - - return ("'({} (ID: {}) = ({}))'.format({})" - .format(self.fullname, hex(self.id), args, args_format)) - class TLArg: def __init__(self, name, arg_type, generic_definition): diff --git a/telethon_generator/tl_generator.py b/telethon_generator/tl_generator.py index cc62c91d..6942b6c9 100644 --- a/telethon_generator/tl_generator.py +++ b/telethon_generator/tl_generator.py @@ -7,6 +7,7 @@ from collections import defaultdict from .source_builder import SourceBuilder from .parsers import TLObject, parse_tl, find_layer +from .utils import snake_to_camel_case AUTO_GEN_NOTICE = \ '"""File generated by TLObjects\' generator. All changes will be ERASED"""' @@ -113,7 +114,7 @@ class TLGenerator: if tlobject.namespace: builder.write('.' + tlobject.namespace) - builder.writeln('.{},', tlobject.class_name()) + builder.writeln('.{},', tlobject.class_name) builder.current_indent -= 1 builder.writeln('}') @@ -173,10 +174,10 @@ class TLGenerator: pass elif len(constructors) == 1: type_defs.append('Type{} = {}'.format( - type_name, constructors[0].class_name())) + type_name, constructors[0].class_name)) else: type_defs.append('Type{} = Union[{}]'.format( - type_name, ','.join(c.class_name() + type_name, ','.join(c.class_name for c in constructors))) imports = {} @@ -238,7 +239,7 @@ class TLGenerator: """ builder.writeln() builder.writeln() - builder.writeln('class {}(TLObject):', tlobject.class_name()) + builder.writeln('class {}(TLObject):', tlobject.class_name) # Class-level variable to store its Telegram's constructor ID builder.writeln('CONSTRUCTOR_ID = {:#x}', tlobject.id) @@ -297,10 +298,10 @@ class TLGenerator: builder.writeln('This type has no constructors.') elif len(constructors) == 1: builder.writeln('Instance of {}.', - constructors[0].class_name()) + constructors[0].class_name) else: builder.writeln('Instance of either {}.', ', '.join( - c.class_name() for c in constructors)) + c.class_name for c in constructors)) builder.writeln('"""') @@ -365,7 +366,7 @@ class TLGenerator: base_types = ('string', 'bytes', 'int', 'long', 'int128', 'int256', 'double', 'Bool', 'true', 'date') - builder.write("'_': '{}'", tlobject.class_name()) + builder.write("'_': '{}'", tlobject.class_name) for arg in args: builder.writeln(',') builder.write("'{}': ", arg.name) @@ -441,7 +442,7 @@ class TLGenerator: builder.writeln( 'return {}({})', - tlobject.class_name(), + tlobject.class_name, ', '.join( '{0}=_{0}'.format(a.name) for a in tlobject.sorted_args() if not a.flag_indicator and not a.generic_definition @@ -709,7 +710,7 @@ class TLGenerator: ns, t = '.', arg.type else: ns, t = '.' + arg.type[:sep_index], arg.type[sep_index+1:] - class_name = TLObject.class_name_for(t) + class_name = snake_to_camel_case(t) # There would be no need to import the type if we're in the # file with the same namespace, but since it does no harm diff --git a/telethon_generator/utils.py b/telethon_generator/utils.py new file mode 100644 index 00000000..c28c27b4 --- /dev/null +++ b/telethon_generator/utils.py @@ -0,0 +1,8 @@ +import re + + +def snake_to_camel_case(name, suffix=None): + # Courtesy of http://stackoverflow.com/a/31531797/4759433 + result = re.sub(r'_([a-z])', lambda m: m.group(1).upper(), name.lower()) + result = result[:1].upper() + result[1:].replace('_', '') + return result + suffix if suffix else result