mirror of
https://github.com/LonamiWebs/Telethon.git
synced 2024-11-25 10:53:44 +03:00
Add support for flags2 in the TL
This commit is contained in:
parent
f9643bf737
commit
5feb210442
|
@ -164,7 +164,7 @@ def _get_description(arg):
|
||||||
if arg.can_be_inferred:
|
if arg.can_be_inferred:
|
||||||
desc.append('If left unspecified, it will be inferred automatically.')
|
desc.append('If left unspecified, it will be inferred automatically.')
|
||||||
otherwise = True
|
otherwise = True
|
||||||
elif arg.is_flag:
|
elif arg.flag:
|
||||||
desc.append('This argument defaults to '
|
desc.append('This argument defaults to '
|
||||||
'<code>None</code> and can be omitted.')
|
'<code>None</code> and can be omitted.')
|
||||||
otherwise = True
|
otherwise = True
|
||||||
|
|
|
@ -187,9 +187,9 @@ def _write_class_init(tlobject, kind, type_constructors, builder):
|
||||||
crc32(tlobject.result.encode('ascii')))
|
crc32(tlobject.result.encode('ascii')))
|
||||||
builder.writeln()
|
builder.writeln()
|
||||||
|
|
||||||
# Convert the args to string parameters, flags having =None
|
# Convert the args to string parameters, those with flag having =None
|
||||||
args = ['{}: {}{}'.format(
|
args = ['{}: {}{}'.format(
|
||||||
a.name, a.type_hint(), '=None' if a.is_flag or a.can_be_inferred else '')
|
a.name, a.type_hint(), '=None' if a.flag or a.can_be_inferred else '')
|
||||||
for a in tlobject.real_args
|
for a in tlobject.real_args
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -266,7 +266,7 @@ def _write_resolve(tlobject, builder):
|
||||||
if not ac:
|
if not ac:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if arg.is_flag:
|
if arg.flag:
|
||||||
builder.writeln('if self.{}:', arg.name)
|
builder.writeln('if self.{}:', arg.name)
|
||||||
|
|
||||||
if arg.is_vector:
|
if arg.is_vector:
|
||||||
|
@ -279,7 +279,7 @@ def _write_resolve(tlobject, builder):
|
||||||
builder.writeln('self.{} = {}', arg.name,
|
builder.writeln('self.{} = {}', arg.name,
|
||||||
ac.format('self.' + arg.name))
|
ac.format('self.' + arg.name))
|
||||||
|
|
||||||
if arg.is_flag:
|
if arg.flag:
|
||||||
builder.end_block()
|
builder.end_block()
|
||||||
builder.end_block()
|
builder.end_block()
|
||||||
|
|
||||||
|
@ -327,8 +327,8 @@ def _write_to_bytes(tlobject, builder):
|
||||||
# at the same time. In this case, add an assertion.
|
# at the same time. In this case, add an assertion.
|
||||||
repeated_args = defaultdict(list)
|
repeated_args = defaultdict(list)
|
||||||
for arg in tlobject.args:
|
for arg in tlobject.args:
|
||||||
if arg.is_flag:
|
if arg.flag:
|
||||||
repeated_args[arg.flag_index].append(arg)
|
repeated_args[(arg.flag, arg.flag_index)].append(arg)
|
||||||
|
|
||||||
for ra in repeated_args.values():
|
for ra in repeated_args.values():
|
||||||
if len(ra) > 1:
|
if len(ra) > 1:
|
||||||
|
@ -416,7 +416,7 @@ def _write_arg_to_bytes(builder, arg, tlobject, name=None):
|
||||||
# if it's not a True type.
|
# if it's not a True type.
|
||||||
# True types are not actually sent, but instead only used to
|
# True types are not actually sent, but instead only used to
|
||||||
# determine the flags.
|
# determine the flags.
|
||||||
if arg.is_flag:
|
if arg.flag:
|
||||||
if arg.type == 'true':
|
if arg.type == 'true':
|
||||||
return # Exit, since True type is never written
|
return # Exit, since True type is never written
|
||||||
elif arg.is_vector:
|
elif arg.is_vector:
|
||||||
|
@ -444,31 +444,31 @@ def _write_arg_to_bytes(builder, arg, tlobject, name=None):
|
||||||
builder.write("b''.join(")
|
builder.write("b''.join(")
|
||||||
|
|
||||||
# Temporary disable .is_vector, not to enter this if again
|
# Temporary disable .is_vector, not to enter this if again
|
||||||
# Also disable .is_flag since it's not needed per element
|
# Also disable .flag since it's not needed per element
|
||||||
old_flag = arg.is_flag
|
old_flag, arg.flag = arg.flag, None
|
||||||
arg.is_vector = arg.is_flag = False
|
arg.is_vector = False
|
||||||
_write_arg_to_bytes(builder, arg, tlobject, name='x')
|
_write_arg_to_bytes(builder, arg, tlobject, name='x')
|
||||||
arg.is_vector = True
|
arg.is_vector = True
|
||||||
arg.is_flag = old_flag
|
arg.flag = old_flag
|
||||||
|
|
||||||
builder.write(' for x in {})', name)
|
builder.write(' for x in {})', name)
|
||||||
|
|
||||||
elif arg.flag_indicator:
|
elif arg.flag_indicator:
|
||||||
# Calculate the flags with those items which are not None
|
# Calculate the flags with those items which are not None
|
||||||
if not any(f.is_flag for f in tlobject.args):
|
if not any(f.flag for f in tlobject.args):
|
||||||
# There's a flag indicator, but no flag arguments so it's 0
|
# There's a flag indicator, but no flag arguments so it's 0
|
||||||
builder.write(r"b'\0\0\0\0'")
|
builder.write(r"b'\0\0\0\0'")
|
||||||
else:
|
else:
|
||||||
def fmt_flag(flag):
|
def fmt_flag_arg(a):
|
||||||
if flag.type == 'Bool':
|
if a.type == 'Bool':
|
||||||
fmt = '(0 if {0} is None else {1})'
|
fmt = '(0 if {0} is None else {1})'
|
||||||
else:
|
else:
|
||||||
fmt = '(0 if {0} is None or {0} is False else {1})'
|
fmt = '(0 if {0} is None or {0} is False else {1})'
|
||||||
return fmt.format('self.{}'.format(flag.name), 1 << flag.flag_index)
|
return fmt.format('self.{}'.format(a.name), 1 << a.flag_index)
|
||||||
|
|
||||||
builder.write("struct.pack('<I', ")
|
builder.write("struct.pack('<I', ")
|
||||||
builder.write(
|
builder.write(
|
||||||
' | '.join(fmt_flag(flag) for flag in tlobject.args if flag.is_flag)
|
' | '.join(fmt_flag_arg(a) for a in tlobject.args if a.flag == arg.name)
|
||||||
)
|
)
|
||||||
builder.write(')')
|
builder.write(')')
|
||||||
|
|
||||||
|
@ -520,7 +520,7 @@ def _write_arg_to_bytes(builder, arg, tlobject, name=None):
|
||||||
if not boxed:
|
if not boxed:
|
||||||
builder.write('[4:]')
|
builder.write('[4:]')
|
||||||
|
|
||||||
if arg.is_flag:
|
if arg.flag:
|
||||||
builder.write(')')
|
builder.write(')')
|
||||||
if arg.is_vector:
|
if arg.is_vector:
|
||||||
builder.write(')') # We were using a tuple
|
builder.write(')') # We were using a tuple
|
||||||
|
@ -545,20 +545,19 @@ def _write_arg_read_code(builder, arg, tlobject, name):
|
||||||
return # Do nothing, this only specifies a later type
|
return # Do nothing, this only specifies a later type
|
||||||
|
|
||||||
# The argument may be a flag, only write that flag was given!
|
# The argument may be a flag, only write that flag was given!
|
||||||
was_flag = False
|
old_flag = None
|
||||||
if arg.is_flag:
|
if arg.flag:
|
||||||
# Treat 'true' flags as a special case, since they're true if
|
# Treat 'true' flags as a special case, since they're true if
|
||||||
# they're set, and nothing else needs to actually be read.
|
# they're set, and nothing else needs to actually be read.
|
||||||
if 'true' == arg.type:
|
if 'true' == arg.type:
|
||||||
builder.writeln('{} = bool(flags & {})',
|
builder.writeln('{} = bool({} & {})',
|
||||||
name, 1 << arg.flag_index)
|
name, arg.flag, 1 << arg.flag_index)
|
||||||
return
|
return
|
||||||
|
|
||||||
was_flag = True
|
builder.writeln('if {} & {}:', arg.flag, 1 << arg.flag_index)
|
||||||
builder.writeln('if flags & {}:', 1 << arg.flag_index)
|
# Temporary disable .flag not to enter this if
|
||||||
# Temporary disable .is_flag not to enter this if
|
|
||||||
# again when calling the method recursively
|
# again when calling the method recursively
|
||||||
arg.is_flag = False
|
old_flag, arg.flag = arg.flag, None
|
||||||
|
|
||||||
if arg.is_vector:
|
if arg.is_vector:
|
||||||
if arg.use_vector_id:
|
if arg.use_vector_id:
|
||||||
|
@ -575,7 +574,7 @@ def _write_arg_read_code(builder, arg, tlobject, name):
|
||||||
|
|
||||||
elif arg.flag_indicator:
|
elif arg.flag_indicator:
|
||||||
# Read the flags, which will indicate what items we should read next
|
# Read the flags, which will indicate what items we should read next
|
||||||
builder.writeln('flags = reader.read_int()')
|
builder.writeln('{} = reader.read_int()', arg.name)
|
||||||
builder.writeln()
|
builder.writeln()
|
||||||
|
|
||||||
elif 'int' == arg.type:
|
elif 'int' == arg.type:
|
||||||
|
@ -643,13 +642,13 @@ def _write_arg_read_code(builder, arg, tlobject, name):
|
||||||
if arg.is_vector:
|
if arg.is_vector:
|
||||||
builder.end_block()
|
builder.end_block()
|
||||||
|
|
||||||
if was_flag:
|
if old_flag:
|
||||||
builder.current_indent -= 1
|
builder.current_indent -= 1
|
||||||
builder.writeln('else:')
|
builder.writeln('else:')
|
||||||
builder.writeln('{} = None', name)
|
builder.writeln('{} = None', name)
|
||||||
builder.current_indent -= 1
|
builder.current_indent -= 1
|
||||||
# Restore .is_flag
|
# Restore .flag
|
||||||
arg.is_flag = True
|
arg.flag = old_flag
|
||||||
|
|
||||||
|
|
||||||
def _write_all_tlobjects(tlobjects, layer, builder):
|
def _write_all_tlobjects(tlobjects, layer, builder):
|
||||||
|
|
|
@ -100,9 +100,9 @@ class TLArg:
|
||||||
|
|
||||||
# Default values
|
# Default values
|
||||||
self.is_vector = False
|
self.is_vector = False
|
||||||
self.is_flag = False
|
self.flag = None # name of the flag to check if self is present
|
||||||
self.skip_constructor_id = False
|
self.skip_constructor_id = False
|
||||||
self.flag_index = -1
|
self.flag_index = -1 # bit index of the flag to check if self is present
|
||||||
self.cls = None
|
self.cls = None
|
||||||
|
|
||||||
# Special case: some types can be inferred, which makes it
|
# Special case: some types can be inferred, which makes it
|
||||||
|
@ -122,16 +122,14 @@ class TLArg:
|
||||||
# Strip the exclamation mark always to have only the name
|
# Strip the exclamation mark always to have only the name
|
||||||
self.type = arg_type.lstrip('!')
|
self.type = arg_type.lstrip('!')
|
||||||
|
|
||||||
# The type may be a flag (flags.IDX?REAL_TYPE)
|
# The type may be a flag (FLAGS.IDX?REAL_TYPE)
|
||||||
# Note that 'flags' is NOT the flags name; this
|
# FLAGS can be any name, but it should have appeared previously.
|
||||||
# is determined by a previous argument
|
flag_match = re.match(r'(\w+).(\d+)\?([\w<>.]+)', self.type)
|
||||||
# However, we assume that the argument will always be called 'flags'
|
|
||||||
flag_match = re.match(r'flags.(\d+)\?([\w<>.]+)', self.type)
|
|
||||||
if flag_match:
|
if flag_match:
|
||||||
self.is_flag = True
|
self.flag = flag_match.group(1)
|
||||||
self.flag_index = int(flag_match.group(1))
|
self.flag_index = int(flag_match.group(2))
|
||||||
# Update the type to match the exact type, not the "flagged" one
|
# Update the type to match the exact type, not the "flagged" one
|
||||||
self.type = flag_match.group(2)
|
self.type = flag_match.group(3)
|
||||||
|
|
||||||
# Then check if the type is a Vector<REAL_TYPE>
|
# Then check if the type is a Vector<REAL_TYPE>
|
||||||
vector_match = re.match(r'[Vv]ector<([\w\d.]+)>', self.type)
|
vector_match = re.match(r'[Vv]ector<([\w\d.]+)>', self.type)
|
||||||
|
@ -180,7 +178,7 @@ class TLArg:
|
||||||
}.get(cls, "'Type{}'".format(cls))
|
}.get(cls, "'Type{}'".format(cls))
|
||||||
if self.is_vector:
|
if self.is_vector:
|
||||||
result = 'List[{}]'.format(result)
|
result = 'List[{}]'.format(result)
|
||||||
if self.is_flag and cls != 'date':
|
if self.flag and cls != 'date':
|
||||||
result = 'Optional[{}]'.format(result)
|
result = 'Optional[{}]'.format(result)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
@ -200,8 +198,8 @@ class TLArg:
|
||||||
if self.is_generic:
|
if self.is_generic:
|
||||||
real_type = '!{}'.format(real_type)
|
real_type = '!{}'.format(real_type)
|
||||||
|
|
||||||
if self.is_flag:
|
if self.flag:
|
||||||
real_type = 'flags.{}?{}'.format(self.flag_index, real_type)
|
real_type = '{}.{}?{}'.format(self.flag, self.flag_index, real_type)
|
||||||
|
|
||||||
return real_type
|
return real_type
|
||||||
|
|
||||||
|
@ -244,5 +242,5 @@ class TLArg:
|
||||||
self.cls[0].as_example(f, indent)
|
self.cls[0].as_example(f, indent)
|
||||||
|
|
||||||
def omit_example(self):
|
def omit_example(self):
|
||||||
return (self.is_flag or self.can_be_inferred) \
|
return (self.flag or self.can_be_inferred) \
|
||||||
and self.name in OMITTED_EXAMPLES
|
and self.name in OMITTED_EXAMPLES
|
||||||
|
|
|
@ -72,7 +72,7 @@ class TLObject:
|
||||||
can be inferred will go last so they can default =None)
|
can be inferred will go last so they can default =None)
|
||||||
"""
|
"""
|
||||||
return sorted(self.args,
|
return sorted(self.args,
|
||||||
key=lambda x: x.is_flag or x.can_be_inferred)
|
key=lambda x: bool(x.flag) or x.can_be_inferred)
|
||||||
|
|
||||||
def __repr__(self, ignore_id=False):
|
def __repr__(self, ignore_id=False):
|
||||||
if self.id is None or ignore_id:
|
if self.id is None or ignore_id:
|
||||||
|
@ -95,8 +95,9 @@ class TLObject:
|
||||||
.replace('<', ' ').replace('>', '')\
|
.replace('<', ' ').replace('>', '')\
|
||||||
.replace('{', '').replace('}', '')
|
.replace('{', '').replace('}', '')
|
||||||
|
|
||||||
|
# Remove optional empty values (special-cased to the true type)
|
||||||
representation = re.sub(
|
representation = re.sub(
|
||||||
r' \w+:flags\.\d+\?true',
|
r' \w+:\w+\.\d+\?true',
|
||||||
r'',
|
r'',
|
||||||
representation
|
representation
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user