mirror of
				https://github.com/LonamiWebs/Telethon.git
				synced 2025-10-31 07:57:38 +03:00 
			
		
		
		
	Make the TLGenerator class a lot more readable
This commit is contained in:
		
							parent
							
								
									68a625b82b
								
							
						
					
					
						commit
						769692959f
					
				|  | @ -110,223 +110,14 @@ class TLGenerator: | ||||||
|                         TLGenerator.get_class_name(tlobject))) |                         TLGenerator.get_class_name(tlobject))) | ||||||
| 
 | 
 | ||||||
|             # Create the file for this TLObject |             # Create the file for this TLObject | ||||||
|             filename = os.path.join( |             filename = os.path.join(out_dir, TLGenerator.get_file_name( | ||||||
|                 out_dir, |                 tlobject, add_extension=True | ||||||
|                 TLGenerator.get_file_name( |             )) | ||||||
|                     tlobject, add_extension=True)) |  | ||||||
| 
 | 
 | ||||||
|             with open(filename, 'w', encoding='utf-8') as file: |             with open(filename, 'w', encoding='utf-8') as file: | ||||||
|                 # Let's build the source code! |  | ||||||
|                 with SourceBuilder(file) as builder: |                 with SourceBuilder(file) as builder: | ||||||
|                     # Both types and functions inherit from |                     TLGenerator._write_source_code( | ||||||
|                     # MTProtoRequest so they all can be sent |                         tlobject, builder, depth, type_constructors) | ||||||
|                     builder.writeln('from {}.tl.mtproto_request import MTProtoRequest' |  | ||||||
|                                     .format('.' * depth)) |  | ||||||
| 
 |  | ||||||
|                     if any(a for a in tlobject.args if a.can_be_inferred): |  | ||||||
|                         # Currently only 'random_id' needs 'os' to be imported |  | ||||||
|                         builder.writeln('import os') |  | ||||||
| 
 |  | ||||||
|                     builder.writeln() |  | ||||||
|                     builder.writeln() |  | ||||||
|                     builder.writeln('class {}(MTProtoRequest):'.format( |  | ||||||
|                         TLGenerator.get_class_name(tlobject))) |  | ||||||
| 
 |  | ||||||
|                     # Write the original .tl definition, |  | ||||||
|                     # along with a "generated automatically" message |  | ||||||
|                     builder.writeln( |  | ||||||
|                         '"""Class generated by TLObjects\' generator. ' |  | ||||||
|                         'All changes will be ERASED. TL definition below.') |  | ||||||
|                     builder.writeln('{}"""'.format(repr(tlobject))) |  | ||||||
|                     builder.writeln() |  | ||||||
| 
 |  | ||||||
|                     # Class-level variable to store its constructor ID |  | ||||||
|                     builder.writeln( |  | ||||||
|                         "# Telegram's constructor (U)ID for this class") |  | ||||||
|                     builder.writeln('constructor_id = {}'.format( |  | ||||||
|                         hex(tlobject.id))) |  | ||||||
|                     builder.writeln() |  | ||||||
| 
 |  | ||||||
|                     # Flag arguments must go last |  | ||||||
|                     args = [ |  | ||||||
|                         a for a in tlobject.sorted_args() |  | ||||||
|                         if not a.flag_indicator and not a.generic_definition |  | ||||||
|                     ] |  | ||||||
| 
 |  | ||||||
|                     # Convert the args to string parameters, flags having =None |  | ||||||
|                     args = [ |  | ||||||
|                         (a.name if not a.is_flag and not a.can_be_inferred |  | ||||||
|                          else '{}=None'.format(a.name)) |  | ||||||
|                         for a in args |  | ||||||
|                     ] |  | ||||||
| 
 |  | ||||||
|                     # Write the __init__ function |  | ||||||
|                     if args: |  | ||||||
|                         builder.writeln('def __init__(self, {}):'.format( |  | ||||||
|                             ', '.join(args))) |  | ||||||
|                     else: |  | ||||||
|                         builder.writeln('def __init__(self):') |  | ||||||
| 
 |  | ||||||
|                     # Now update args to have the TLObject arguments, _except_ |  | ||||||
|                     # those which are calculated on send or ignored, this is |  | ||||||
|                     # flag indicator and generic definitions. |  | ||||||
|                     # |  | ||||||
|                     # We don't need the generic definitions in Python |  | ||||||
|                     # because arguments can be any type |  | ||||||
|                     args = [arg for arg in tlobject.args |  | ||||||
|                             if not arg.flag_indicator and |  | ||||||
|                             not arg.generic_definition] |  | ||||||
| 
 |  | ||||||
|                     if args: |  | ||||||
|                         # Write the docstring, to know the type of the args |  | ||||||
|                         builder.writeln('"""') |  | ||||||
|                         for arg in args: |  | ||||||
|                             if not arg.flag_indicator: |  | ||||||
|                                 builder.write( |  | ||||||
|                                     ':param {}: Telegram type: "{}".' |  | ||||||
|                                         .format(arg.name, arg.type) |  | ||||||
|                                 ) |  | ||||||
|                                 if arg.is_vector: |  | ||||||
|                                     builder.write( |  | ||||||
|                                         ' Must be a list.'.format(arg.name) |  | ||||||
|                                     ) |  | ||||||
|                                 if arg.is_generic: |  | ||||||
|                                     builder.write( |  | ||||||
|                                         ' Must be another MTProtoRequest.' |  | ||||||
|                                     ) |  | ||||||
|                                 builder.writeln() |  | ||||||
| 
 |  | ||||||
|                         # We also want to know what type this request returns |  | ||||||
|                         # or to which type this constructor belongs to |  | ||||||
|                         builder.writeln() |  | ||||||
|                         if tlobject.is_function: |  | ||||||
|                             builder.write(':returns %s: ' % tlobject.result) |  | ||||||
|                         else: |  | ||||||
|                             builder.write('Constructor for %s: ' % tlobject.result) |  | ||||||
| 
 |  | ||||||
|                         constructors = type_constructors[tlobject.result] |  | ||||||
|                         if not constructors: |  | ||||||
|                             builder.writeln('This type has no constructors.') |  | ||||||
|                         elif len(constructors) == 1: |  | ||||||
|                             builder.writeln('Instance of {}.'.format( |  | ||||||
|                                 TLGenerator.get_class_name(constructors[0]) |  | ||||||
|                             )) |  | ||||||
|                         else: |  | ||||||
|                             builder.writeln('Instance of either {}.'.format( |  | ||||||
|                                 ', '.join(TLGenerator.get_class_name(c) |  | ||||||
|                                           for c in constructors) |  | ||||||
|                             )) |  | ||||||
| 
 |  | ||||||
|                         builder.writeln('"""') |  | ||||||
| 
 |  | ||||||
|                     builder.writeln('super().__init__()') |  | ||||||
|                     # Functions have a result object and are confirmed by default |  | ||||||
|                     if tlobject.is_function: |  | ||||||
|                         builder.writeln('self.result = None') |  | ||||||
|                         builder.writeln( |  | ||||||
|                             'self.confirmed = True  # Confirmed by default') |  | ||||||
| 
 |  | ||||||
|                     # Set the arguments |  | ||||||
|                     if args: |  | ||||||
|                         # Leave an empty line if there are any args |  | ||||||
|                         builder.writeln() |  | ||||||
| 
 |  | ||||||
|                     for arg in args: |  | ||||||
|                         if arg.can_be_inferred: |  | ||||||
|                             # Currently the only argument that can be |  | ||||||
|                             # inferred are those called 'random_id' |  | ||||||
|                             if arg.name == 'random_id': |  | ||||||
|                                 builder.writeln( |  | ||||||
|                                     "self.random_id = random_id if random_id " |  | ||||||
|                                     "is not None else int.from_bytes(" |  | ||||||
|                                     "os.urandom({}), signed=True, " |  | ||||||
|                                     "byteorder='little')" |  | ||||||
|                                         .format(8 if arg.type == 'long' else 4) |  | ||||||
|                                 ) |  | ||||||
|                             else: |  | ||||||
|                                 raise ValueError( |  | ||||||
|                                     'Cannot infer a value for ', arg) |  | ||||||
|                         else: |  | ||||||
|                             builder.writeln('self.{0} = {0}' |  | ||||||
|                                             .format(arg.name)) |  | ||||||
| 
 |  | ||||||
|                     builder.end_block() |  | ||||||
|                      |  | ||||||
|                     # Write the to_dict(self) method |  | ||||||
|                     builder.writeln('def to_dict(self):') |  | ||||||
|                     if args: |  | ||||||
|                         builder.writeln('return {') |  | ||||||
|                          |  | ||||||
|                         base_types = ['string', 'bytes', 'int', 'long', |  | ||||||
|                                       'int128', 'int256', 'double', 'Bool', |  | ||||||
|                                       'true', 'date'] |  | ||||||
|                          |  | ||||||
|                         for arg in args: |  | ||||||
|                             builder.writeln("'{}': ".format(arg.name)) |  | ||||||
|                             if arg.is_vector: |  | ||||||
|                                 builder.writeln('[x{} for x in self.{}] if self.{} is not None else [],' |  | ||||||
|                                                 .format('.to_dict() if x is not None else None' |  | ||||||
|                                                                   if arg.type not in base_types else '', |  | ||||||
|                                                         arg.name, arg.name)) |  | ||||||
|                             else: |  | ||||||
|                                 builder.writeln( |  | ||||||
|                                     'self.{}{},'.format( |  | ||||||
|                                         arg.name, |  | ||||||
|                                         '.to_dict() if self.{} is not None else None' |  | ||||||
|                                             .format(arg.name) if arg.type not in base_types else '')) |  | ||||||
|                         builder.write("}") |  | ||||||
|                     else: |  | ||||||
|                         builder.writeln('return {}') |  | ||||||
|                     builder.writeln() |  | ||||||
|                     builder.end_block() |  | ||||||
| 
 |  | ||||||
|                     # Write the on_send(self, writer) function |  | ||||||
|                     builder.writeln('def on_send(self, writer):') |  | ||||||
|                     builder.writeln( |  | ||||||
|                         'writer.write_int({}.constructor_id, signed=False)' |  | ||||||
|                         .format(TLGenerator.get_class_name(tlobject))) |  | ||||||
| 
 |  | ||||||
|                     for arg in tlobject.args: |  | ||||||
|                         TLGenerator.write_onsend_code(builder, arg, |  | ||||||
|                                                       tlobject.args) |  | ||||||
|                     builder.end_block() |  | ||||||
| 
 |  | ||||||
|                     # Write the empty() function, which returns an "empty" |  | ||||||
|                     # instance, in which all attributes are set to None |  | ||||||
|                     builder.writeln('@staticmethod') |  | ||||||
|                     builder.writeln('def empty():') |  | ||||||
|                     builder.writeln( |  | ||||||
|                         '"""Returns an "empty" instance (attributes=None)"""') |  | ||||||
|                     builder.writeln('return {}({})'.format( |  | ||||||
|                         TLGenerator.get_class_name(tlobject), ', '.join( |  | ||||||
|                             'None' for _ in range(len(args))))) |  | ||||||
|                     builder.end_block() |  | ||||||
| 
 |  | ||||||
|                     # Write the on_response(self, reader) function |  | ||||||
|                     builder.writeln('def on_response(self, reader):') |  | ||||||
|                     # Do not read constructor's ID, since |  | ||||||
|                     # that's already been read somewhere else |  | ||||||
|                     if tlobject.is_function: |  | ||||||
|                         TLGenerator.write_request_result_code(builder, tlobject) |  | ||||||
|                     else: |  | ||||||
|                         if tlobject.args: |  | ||||||
|                             for arg in tlobject.args: |  | ||||||
|                                 TLGenerator.write_onresponse_code( |  | ||||||
|                                     builder, arg, tlobject.args) |  | ||||||
|                         else: |  | ||||||
|                             # If there were no arguments, we still need an |  | ||||||
|                             # on_response method, and hence "pass" if empty |  | ||||||
|                             builder.writeln('pass') |  | ||||||
|                     builder.end_block() |  | ||||||
| 
 |  | ||||||
|                     # Write the __repr__(self) and __str__(self) functions |  | ||||||
|                     builder.writeln('def __repr__(self):') |  | ||||||
|                     builder.writeln("return '{}'".format(repr(tlobject))) |  | ||||||
|                     builder.end_block() |  | ||||||
| 
 |  | ||||||
|                     builder.writeln('def __str__(self):') |  | ||||||
|                     builder.writeln('return {}'.format(str(tlobject))) |  | ||||||
|                     # builder.end_block()  # No need to end the last block |  | ||||||
| 
 | 
 | ||||||
|         # Step 3: Add the relative imports to the namespaces on __init__.py's |         # Step 3: Add the relative imports to the namespaces on __init__.py's | ||||||
|         init_py = os.path.join(get_output_path('functions'), '__init__.py') |         init_py = os.path.join(get_output_path('functions'), '__init__.py') | ||||||
|  | @ -380,6 +171,236 @@ class TLGenerator: | ||||||
|                 builder.current_indent -= 1 |                 builder.current_indent -= 1 | ||||||
|                 builder.writeln('}') |                 builder.writeln('}') | ||||||
| 
 | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def _write_source_code(tlobject, builder, depth, type_constructors): | ||||||
|  |         """Writes the source code corresponding to the given TLObject | ||||||
|  |            by making use of the 'builder' SourceBuilder. | ||||||
|  | 
 | ||||||
|  |            Additional information such as file path depth and | ||||||
|  |            the Type: [Constructors] must be given for proper | ||||||
|  |            importing and documentation strings. | ||||||
|  |         '""" | ||||||
|  | 
 | ||||||
|  |         # Both types and functions inherit from | ||||||
|  |         # MTProtoRequest so they all can be sent | ||||||
|  |         builder.writeln('from {}.tl.mtproto_request import MTProtoRequest' | ||||||
|  |                         .format('.' * depth)) | ||||||
|  | 
 | ||||||
|  |         if any(a for a in tlobject.args if a.can_be_inferred): | ||||||
|  |             # Currently only 'random_id' needs 'os' to be imported | ||||||
|  |             builder.writeln('import os') | ||||||
|  | 
 | ||||||
|  |         builder.writeln() | ||||||
|  |         builder.writeln() | ||||||
|  |         builder.writeln('class {}(MTProtoRequest):'.format( | ||||||
|  |             TLGenerator.get_class_name(tlobject))) | ||||||
|  | 
 | ||||||
|  |         # Write the original .tl definition, | ||||||
|  |         # along with a "generated automatically" message | ||||||
|  |         builder.writeln( | ||||||
|  |             '"""Class generated by TLObjects\' generator. ' | ||||||
|  |             'All changes will be ERASED. TL definition below.' | ||||||
|  |         ) | ||||||
|  |         builder.writeln('{}"""'.format(repr(tlobject))) | ||||||
|  |         builder.writeln() | ||||||
|  | 
 | ||||||
|  |         # Class-level variable to store its constructor ID | ||||||
|  |         builder.writeln("# Telegram's constructor (U)ID for this class") | ||||||
|  |         builder.writeln('constructor_id = {}'.format(hex(tlobject.id))) | ||||||
|  |         builder.writeln() | ||||||
|  | 
 | ||||||
|  |         # Flag arguments must go last | ||||||
|  |         args = [ | ||||||
|  |             a for a in tlobject.sorted_args() | ||||||
|  |             if not a.flag_indicator and not a.generic_definition | ||||||
|  |         ] | ||||||
|  | 
 | ||||||
|  |         # Convert the args to string parameters, flags having =None | ||||||
|  |         args = [ | ||||||
|  |             (a.name if not a.is_flag and not a.can_be_inferred | ||||||
|  |              else '{}=None'.format(a.name)) | ||||||
|  |             for a in args | ||||||
|  |         ] | ||||||
|  | 
 | ||||||
|  |         # Write the __init__ function | ||||||
|  |         if args: | ||||||
|  |             builder.writeln( | ||||||
|  |                 'def __init__(self, {}):'.format(', '.join(args)) | ||||||
|  |             ) | ||||||
|  |         else: | ||||||
|  |             builder.writeln('def __init__(self):') | ||||||
|  | 
 | ||||||
|  |         # Now update args to have the TLObject arguments, _except_ | ||||||
|  |         # those which are calculated on send or ignored, this is | ||||||
|  |         # flag indicator and generic definitions. | ||||||
|  |         # | ||||||
|  |         # We don't need the generic definitions in Python | ||||||
|  |         # because arguments can be any type | ||||||
|  |         args = [arg for arg in tlobject.args | ||||||
|  |                 if not arg.flag_indicator and | ||||||
|  |                 not arg.generic_definition] | ||||||
|  | 
 | ||||||
|  |         if args: | ||||||
|  |             # Write the docstring, to know the type of the args | ||||||
|  |             builder.writeln('"""') | ||||||
|  |             for arg in args: | ||||||
|  |                 if not arg.flag_indicator: | ||||||
|  |                     builder.write( | ||||||
|  |                         ':param {}: Telegram type: "{}".' | ||||||
|  |                         .format(arg.name, arg.type) | ||||||
|  |                     ) | ||||||
|  |                     if arg.is_vector: | ||||||
|  |                         builder.write(' Must be a list.'.format(arg.name)) | ||||||
|  | 
 | ||||||
|  |                     if arg.is_generic: | ||||||
|  |                         builder.write(' Must be another MTProtoRequest.') | ||||||
|  | 
 | ||||||
|  |                     builder.writeln() | ||||||
|  | 
 | ||||||
|  |             # We also want to know what type this request returns | ||||||
|  |             # or to which type this constructor belongs to | ||||||
|  |             builder.writeln() | ||||||
|  |             if tlobject.is_function: | ||||||
|  |                 builder.write(':returns {}: '.format(tlobject.result)) | ||||||
|  |             else: | ||||||
|  |                 builder.write('Constructor for {}: '.format(tlobject.result)) | ||||||
|  | 
 | ||||||
|  |             constructors = type_constructors[tlobject.result] | ||||||
|  |             if not constructors: | ||||||
|  |                 builder.writeln('This type has no constructors.') | ||||||
|  |             elif len(constructors) == 1: | ||||||
|  |                 builder.writeln('Instance of {}.'.format( | ||||||
|  |                     TLGenerator.get_class_name(constructors[0]) | ||||||
|  |                 )) | ||||||
|  |             else: | ||||||
|  |                 builder.writeln('Instance of either {}.'.format( | ||||||
|  |                     ', '.join(TLGenerator.get_class_name(c) | ||||||
|  |                               for c in constructors) | ||||||
|  |                 )) | ||||||
|  | 
 | ||||||
|  |             builder.writeln('"""') | ||||||
|  | 
 | ||||||
|  |         builder.writeln('super().__init__()') | ||||||
|  |         # Functions have a result object and are confirmed by default | ||||||
|  |         if tlobject.is_function: | ||||||
|  |             builder.writeln('self.result = None') | ||||||
|  |             builder.writeln( | ||||||
|  |                 'self.confirmed = True  # Confirmed by default') | ||||||
|  | 
 | ||||||
|  |         # Set the arguments | ||||||
|  |         if args: | ||||||
|  |             # Leave an empty line if there are any args | ||||||
|  |             builder.writeln() | ||||||
|  | 
 | ||||||
|  |         for arg in args: | ||||||
|  |             if arg.can_be_inferred: | ||||||
|  |                 # Currently the only argument that can be | ||||||
|  |                 # inferred are those called 'random_id' | ||||||
|  |                 if arg.name == 'random_id': | ||||||
|  |                     builder.writeln( | ||||||
|  |                         "self.random_id = random_id if random_id " | ||||||
|  |                         "is not None else int.from_bytes(" | ||||||
|  |                         "os.urandom({}), signed=True, " | ||||||
|  |                         "byteorder='little')" | ||||||
|  |                         .format(8 if arg.type == 'long' else 4) | ||||||
|  |                     ) | ||||||
|  |                 else: | ||||||
|  |                     raise ValueError('Cannot infer a value for ', arg) | ||||||
|  |             else: | ||||||
|  |                 builder.writeln('self.{0} = {0}'.format(arg.name)) | ||||||
|  | 
 | ||||||
|  |         builder.end_block() | ||||||
|  | 
 | ||||||
|  |         # Write the to_dict(self) method | ||||||
|  |         builder.writeln('def to_dict(self):') | ||||||
|  |         if args: | ||||||
|  |             builder.writeln('return {') | ||||||
|  |             builder.current_indent += 1 | ||||||
|  | 
 | ||||||
|  |             base_types = ('string', 'bytes', 'int', 'long', 'int128', | ||||||
|  |                           'int256', 'double', 'Bool', 'true', 'date') | ||||||
|  | 
 | ||||||
|  |             for arg in args: | ||||||
|  |                 builder.write("'{}': ".format(arg.name)) | ||||||
|  |                 if arg.type in base_types: | ||||||
|  |                     if arg.is_vector: | ||||||
|  |                         builder.write( | ||||||
|  |                             '[] if self.{0} is None else self.{0}[:]' | ||||||
|  |                             .format(arg.name) | ||||||
|  |                         ) | ||||||
|  |                     else: | ||||||
|  |                         builder.write('self.{}'.format(arg.name)) | ||||||
|  |                 else: | ||||||
|  |                     if arg.is_vector: | ||||||
|  |                         builder.write( | ||||||
|  |                             '[] if self.{0} is None else [None ' | ||||||
|  |                             'if x is None else x.to_dict() for x in self.{0}]' | ||||||
|  |                             .format(arg.name) | ||||||
|  |                         ) | ||||||
|  |                     else: | ||||||
|  |                         builder.write( | ||||||
|  |                             'None if self.{0} is None else self.{0}.to_dict()' | ||||||
|  |                             .format(arg.name) | ||||||
|  |                         ) | ||||||
|  |                 builder.writeln(',') | ||||||
|  | 
 | ||||||
|  |             builder.current_indent -= 1 | ||||||
|  |             builder.write("}") | ||||||
|  |         else: | ||||||
|  |             builder.writeln('return {}') | ||||||
|  | 
 | ||||||
|  |         builder.writeln() | ||||||
|  |         builder.end_block() | ||||||
|  | 
 | ||||||
|  |         # Write the on_send(self, writer) function | ||||||
|  |         builder.writeln('def on_send(self, writer):') | ||||||
|  |         builder.writeln( | ||||||
|  |             'writer.write_int({}.constructor_id, signed=False)' | ||||||
|  |                 .format(TLGenerator.get_class_name(tlobject))) | ||||||
|  | 
 | ||||||
|  |         for arg in tlobject.args: | ||||||
|  |             TLGenerator.write_onsend_code(builder, arg, | ||||||
|  |                                           tlobject.args) | ||||||
|  |         builder.end_block() | ||||||
|  | 
 | ||||||
|  |         # Write the empty() function, which returns an "empty" | ||||||
|  |         # instance, in which all attributes are set to None | ||||||
|  |         builder.writeln('@staticmethod') | ||||||
|  |         builder.writeln('def empty():') | ||||||
|  |         builder.writeln( | ||||||
|  |             '"""Returns an "empty" instance (attributes=None)"""') | ||||||
|  |         builder.writeln('return {}({})'.format( | ||||||
|  |             TLGenerator.get_class_name(tlobject), ', '.join( | ||||||
|  |                 'None' for _ in range(len(args))))) | ||||||
|  |         builder.end_block() | ||||||
|  | 
 | ||||||
|  |         # Write the on_response(self, reader) function | ||||||
|  |         builder.writeln('def on_response(self, reader):') | ||||||
|  |         # Do not read constructor's ID, since | ||||||
|  |         # that's already been read somewhere else | ||||||
|  |         if tlobject.is_function: | ||||||
|  |             TLGenerator.write_request_result_code(builder, tlobject) | ||||||
|  |         else: | ||||||
|  |             if tlobject.args: | ||||||
|  |                 for arg in tlobject.args: | ||||||
|  |                     TLGenerator.write_onresponse_code( | ||||||
|  |                         builder, arg, tlobject.args) | ||||||
|  |             else: | ||||||
|  |                 # If there were no arguments, we still need an | ||||||
|  |                 # on_response method, and hence "pass" if empty | ||||||
|  |                 builder.writeln('pass') | ||||||
|  |         builder.end_block() | ||||||
|  | 
 | ||||||
|  |         # Write the __repr__(self) and __str__(self) functions | ||||||
|  |         builder.writeln('def __repr__(self):') | ||||||
|  |         builder.writeln("return '{}'".format(repr(tlobject))) | ||||||
|  |         builder.end_block() | ||||||
|  | 
 | ||||||
|  |         builder.writeln('def __str__(self):') | ||||||
|  |         builder.writeln('return {}'.format(str(tlobject))) | ||||||
|  |         # builder.end_block()  # No need to end the last block | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def get_class_name(tlobject): |     def get_class_name(tlobject): | ||||||
|         """Gets the class name following the Python style guidelines, in ThisClassFormat""" |         """Gets the class name following the Python style guidelines, in ThisClassFormat""" | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user