Automatically infer the value for 'random_id' parameters

This commit is contained in:
Lonami Exo
2017-06-11 19:16:59 +02:00
parent 3ed59d08e5
commit 1ca41b5854
4 changed files with 68 additions and 27 deletions

View File

@@ -78,6 +78,14 @@ class TLObject:
result=match.group(3),
is_function=is_function)
def sorted_args(self):
"""Returns the arguments properly sorted and ready to plug-in
into a Python's method header (i.e., flags and those which
can be inferred will go last so they can default =None)
"""
return sorted(self.args,
key=lambda x: x.is_flag or x.can_be_inferred)
def is_core_type(self):
"""Determines whether the TLObject is a "core type"
(and thus should be embedded in the generated code) or not"""
@@ -134,6 +142,12 @@ class TLArg:
self.is_flag = False
self.flag_index = -1
# Special case: some types can be inferred, which makes it
# less annoying to type. Currently the only type that can
# be inferred is if the name is 'random_id', to which a
# random ID will be assigned if left as None (the default)
self.can_be_inferred = name == 'random_id'
# The type can be an indicator that other arguments will be flags
if arg_type == '#':
self.flag_indicator = True

View File

@@ -108,12 +108,18 @@ class TLGenerator:
out_dir,
TLGenerator.get_file_name(
tlobject, add_extension=True))
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
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(
@@ -134,16 +140,17 @@ class TLGenerator:
builder.writeln()
# First sort the arguments so that those not being a flag come first
args = sorted(
[arg for arg in tlobject.args
if not arg.flag_indicator],
key=lambda x: x.is_flag)
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
args = [(arg.name if not arg.is_flag else
'{}=None'.format(arg.name)) for arg in args
if not arg.flag_indicator and
not arg.generic_definition]
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:
@@ -209,8 +216,26 @@ class TLGenerator:
if args:
# Leave an empty line if there are any args
builder.writeln()
for arg in args:
builder.writeln('self.{0} = {0}'.format(arg.name))
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 on_send(self, writer) function