mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-22 09:26:37 +03:00
Try to adhere to the 80-characters limit
This commit is contained in:
parent
76166cd1ec
commit
68a625b82b
|
@ -19,7 +19,9 @@ output_base_depth = 2 # telethon/tl/
|
|||
class TLGenerator:
|
||||
@staticmethod
|
||||
def tlobjects_exist():
|
||||
"""Determines whether the TLObjects were previously generated (hence exist) or not"""
|
||||
"""Determines whether the TLObjects were previously
|
||||
generated (hence exist) or not
|
||||
"""
|
||||
return os.path.isfile(get_output_path('all_tlobjects.py'))
|
||||
|
||||
@staticmethod
|
||||
|
@ -36,25 +38,28 @@ class TLGenerator:
|
|||
|
||||
@staticmethod
|
||||
def generate_tlobjects(scheme_file):
|
||||
"""Generates all the TLObjects from scheme.tl to tl/functions and tl/types"""
|
||||
"""Generates all the TLObjects from scheme.tl to
|
||||
tl/functions and tl/types
|
||||
"""
|
||||
|
||||
# First ensure that the required parent directories exist
|
||||
os.makedirs(get_output_path('functions'), exist_ok=True)
|
||||
os.makedirs(get_output_path('types'), exist_ok=True)
|
||||
|
||||
# Step 0: Store the parsed file in a tuple to avoid parsing it on each iteration
|
||||
# Step 0: Cache the parsed file on a tuple
|
||||
tlobjects = tuple(TLParser.parse_file(scheme_file))
|
||||
|
||||
# Step 1: Ensure that no object has the same name as a namespace
|
||||
# We must check this because Python will complain if it sees a
|
||||
# file and a directory with the same name, which happens for example with "updates"
|
||||
# file and a directory with the same name, which happens for
|
||||
# example with "updates".
|
||||
#
|
||||
# We distinguish between function and type namespaces since we
|
||||
# will later need to perform a relative import for them to be used
|
||||
function_namespaces = set()
|
||||
type_namespaces = set()
|
||||
|
||||
# Now that we're iterating over all the objects we also store Type: [Constructors]
|
||||
# Make use of this iteration to also store 'Type: [Constructors]'
|
||||
type_constructors = defaultdict(list)
|
||||
for tlobject in tlobjects:
|
||||
if tlobject.is_function:
|
||||
|
@ -72,8 +77,9 @@ class TLGenerator:
|
|||
for tlobject in tlobjects:
|
||||
if TLGenerator.get_file_name(tlobject, add_extension=False) \
|
||||
in namespace_directories:
|
||||
# If this TLObject isn't under the same directory as its name (i.e. "contacts"),
|
||||
# append "_tg" to avoid confusion between the file and the directory (i.e. "updates")
|
||||
# If this TLObject isn't under the same directory as its
|
||||
# name (i.e. "contacts"), append "_tg" to avoid confusion
|
||||
# between the file and the directory (i.e. "updates")
|
||||
if tlobject.namespace != tlobject.name:
|
||||
tlobject.name += '_tg'
|
||||
|
||||
|
@ -95,7 +101,7 @@ class TLGenerator:
|
|||
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
|
||||
# Also add this object to __init__.py, so we can import the whole packet at once
|
||||
# Add this object to __init__.py, so we can import *
|
||||
init_py = os.path.join(out_dir, '__init__.py')
|
||||
with open(init_py, 'a', encoding='utf-8') as file:
|
||||
with SourceBuilder(file) as builder:
|
||||
|
@ -112,7 +118,8 @@ class TLGenerator:
|
|||
with open(filename, 'w', encoding='utf-8') as file:
|
||||
# Let's build the source code!
|
||||
with SourceBuilder(file) as builder:
|
||||
# Both types and functions inherit from MTProtoRequest so they all can be sent
|
||||
# Both types and functions inherit from
|
||||
# MTProtoRequest so they all can be sent
|
||||
builder.writeln('from {}.tl.mtproto_request import MTProtoRequest'
|
||||
.format('.' * depth))
|
||||
|
||||
|
@ -125,27 +132,28 @@ class TLGenerator:
|
|||
builder.writeln('class {}(MTProtoRequest):'.format(
|
||||
TLGenerator.get_class_name(tlobject)))
|
||||
|
||||
# Write the original .tl definition, along with a "generated automatically" message
|
||||
# Write the original .tl definition,
|
||||
# along with a "generated automatically" message
|
||||
builder.writeln(
|
||||
'"""Class generated by TLObjects\' generator. '
|
||||
'All changes will be ERASED. Original .tl definition below.')
|
||||
'All changes will be ERASED. TL definition below.')
|
||||
builder.writeln('{}"""'.format(repr(tlobject)))
|
||||
builder.writeln()
|
||||
|
||||
# Create an class-level variable that stores the TLObject's constructor ID
|
||||
# Class-level variable to store its constructor ID
|
||||
builder.writeln(
|
||||
"# Telegram's constructor ID (and unique identifier) for this class")
|
||||
"# Telegram's constructor (U)ID for this class")
|
||||
builder.writeln('constructor_id = {}'.format(
|
||||
hex(tlobject.id)))
|
||||
builder.writeln()
|
||||
|
||||
# First sort the arguments so that those not being a flag come first
|
||||
# Flag arguments must go last
|
||||
args = [
|
||||
a for a in tlobject.sorted_args()
|
||||
if not a.flag_indicator and not a.generic_definition
|
||||
]
|
||||
|
||||
# Then convert the args to string parameters, the flags having =None
|
||||
# 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))
|
||||
|
@ -160,26 +168,32 @@ class TLGenerator:
|
|||
builder.writeln('def __init__(self):')
|
||||
|
||||
# Now update args to have the TLObject arguments, _except_
|
||||
# those which are generated automatically: flag indicator and generic definitions.
|
||||
# We don't need the generic definitions in Python because arguments can be any type
|
||||
# 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, so we know the type of the arguments
|
||||
# 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))
|
||||
':param {}: Telegram type: "{}".'
|
||||
.format(arg.name, arg.type)
|
||||
)
|
||||
if arg.is_vector:
|
||||
builder.write(' Must be a list.'.format(
|
||||
arg.name))
|
||||
builder.write(
|
||||
' Must be a list.'.format(arg.name)
|
||||
)
|
||||
if arg.is_generic:
|
||||
builder.write(
|
||||
' This should be another MTProtoRequest.')
|
||||
' Must be another MTProtoRequest.'
|
||||
)
|
||||
builder.writeln()
|
||||
|
||||
# We also want to know what type this request returns
|
||||
|
@ -243,21 +257,23 @@ class TLGenerator:
|
|||
if args:
|
||||
builder.writeln('return {')
|
||||
|
||||
base_types = ["string", "bytes", "int", "long", "int128", "int256", "double", "Bool", "true",
|
||||
"date"]
|
||||
base_types = ['string', 'bytes', 'int', 'long',
|
||||
'int128', 'int256', 'double', 'Bool',
|
||||
'true', 'date']
|
||||
|
||||
for arg in args:
|
||||
builder.writeln("\'{}\': ".format(arg.name))
|
||||
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 "",
|
||||
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.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 {}')
|
||||
|
@ -280,7 +296,7 @@ class TLGenerator:
|
|||
builder.writeln('@staticmethod')
|
||||
builder.writeln('def empty():')
|
||||
builder.writeln(
|
||||
'"""Returns an "empty" instance (all attributes are None)"""')
|
||||
'"""Returns an "empty" instance (attributes=None)"""')
|
||||
builder.writeln('return {}({})'.format(
|
||||
TLGenerator.get_class_name(tlobject), ', '.join(
|
||||
'None' for _ in range(len(args)))))
|
||||
|
@ -288,7 +304,8 @@ class TLGenerator:
|
|||
|
||||
# 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
|
||||
# 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:
|
||||
|
@ -297,7 +314,8 @@ class TLGenerator:
|
|||
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
|
||||
# If there were no arguments, we still need an
|
||||
# on_response method, and hence "pass" if empty
|
||||
builder.writeln('pass')
|
||||
builder.end_block()
|
||||
|
||||
|
@ -308,7 +326,7 @@ class TLGenerator:
|
|||
|
||||
builder.writeln('def __str__(self):')
|
||||
builder.writeln('return {}'.format(str(tlobject)))
|
||||
# builder.end_block() # There is no need to end the last block
|
||||
# builder.end_block() # No need to end the last block
|
||||
|
||||
# Step 3: Add the relative imports to the namespaces on __init__.py's
|
||||
init_py = os.path.join(get_output_path('functions'), '__init__.py')
|
||||
|
@ -321,7 +339,8 @@ class TLGenerator:
|
|||
file.write('from . import {}\n'
|
||||
.format(', '.join(type_namespaces)))
|
||||
|
||||
# Step 4: Once all the objects have been generated, we can now group them in a single file
|
||||
# Step 4: Once all the objects have been generated,
|
||||
# we can now group them in a single file
|
||||
filename = os.path.join(get_output_path('all_tlobjects.py'))
|
||||
with open(filename, 'w', encoding='utf-8') as file:
|
||||
with SourceBuilder(file) as builder:
|
||||
|
@ -349,7 +368,9 @@ class TLGenerator:
|
|||
constructor = '0x' + constructor[2:].zfill(8)
|
||||
|
||||
builder.write('{}: '.format(constructor))
|
||||
builder.write('functions' if tlobject.is_function else 'types')
|
||||
builder.write(
|
||||
'functions' if tlobject.is_function else 'types')
|
||||
|
||||
if tlobject.namespace:
|
||||
builder.write('.' + tlobject.namespace)
|
||||
|
||||
|
@ -582,9 +603,10 @@ class TLGenerator:
|
|||
:param tlobject: The TLObject for which the 'self.result = ' will be written
|
||||
"""
|
||||
if tlobject.result.startswith('Vector<'):
|
||||
# Vector results are a bit special since they can also be composed of
|
||||
# integer values and such; however, the result of requests is not
|
||||
# parsed as arguments are and it's a bit harder to tell which is which.
|
||||
# Vector results are a bit special since they can also be composed
|
||||
# of integer values and such; however, the result of requests is
|
||||
# not parsed as arguments are and it's a bit harder to tell which
|
||||
# is which.
|
||||
if tlobject.result == 'Vector<int>':
|
||||
builder.writeln('reader.read_int() # Vector id')
|
||||
builder.writeln('count = reader.read_int()')
|
||||
|
|
Loading…
Reference in New Issue
Block a user